[omniORB] [PATCH] Updated omnithread library

Sai-Lai Lo S.Lo@orl.co.uk
Mon, 27 Apr 1998 18:08:22 +0100


A patch is now available to update the omnithread library:

   http://www.orl.co.uk/omniORB/bugs/18.html

This update removes the limitations on mixing omnithreads with native
threads not created by the library:-

- native threads that are not created by the library can call any
  operations in the library and vice versa. Previously, these native
  threads cannot call omni_thread::join and on NT cannot wait on 
  omni_condition.

- The semantics of omni_thread::self() is clarified. If the calling thread
  is not the main thread and is not created using the omnithread library,
  omni_thread::self() returns 0.

If you are using Windows NT/95 and have to use non-omnithreads, you should
consider applying this patch.

Regards,

Sai-Lai


The following test program verifies that the updated version does
work correctly with non-omnithreads:

-------- mix.cc ----------------
#include <omnithread.h>
#include <limits.h>
#include <stdlib.h>
#include <iostream.h>
#ifdef __WIN32__
#include <process.h>
#endif

static omni_mutex     thr_count_lock;
static int            thr_count;
static omni_condition thr_wait(&thr_count_lock);
static void do_something();

#ifdef __WIN32__
static int last_rand = 0;
#endif

static omni_mutex rand_mutex;

static int random_l()
{
    rand_mutex.lock();
    int i = rand();
#ifdef __WIN32__
    last_rand = i;
#endif
    rand_mutex.unlock();
    return i;
}

class realthing_joinable : public omni_thread {
public:
  realthing_joinable() { 
    omni_mutex_lock sync(thr_count_lock);
    thr_count++;
    start_undetached(); 
  }
  ~realthing_joinable() {
    omni_mutex_lock sync(thr_count_lock);
    thr_count--;
    if (!thr_count)
      thr_wait.signal();
  }
  void* run_undetached(void*);
};

class realthing_detached : public omni_thread {
public:
  realthing_detached() { 
    omni_mutex_lock sync(thr_count_lock);
    thr_count++;
    start(); 
  }
  ~realthing_detached() {
    omni_mutex_lock sync(thr_count_lock);
    thr_count--;
    if (!thr_count)
      thr_wait.signal();
  }
  void run(void*);
};


void*
realthing_joinable::run_undetached(void*)
{
  int i=5;
  while (i--) {
    do_something();
  }
  cerr << "realthing_joinable exit." << endl;
  return 0;
}

void
realthing_detached::run(void*)
{
  int i=5;
  while (i--) {
    do_something();
  }
  cerr << "realthing_detached exit." << endl;
}

extern "C"
void*
native_joinable(void*)
{
  realthing_detached* d= new realthing_detached;
  int i=6;
  while (i--) {
    do_something();
  }
  thr_count_lock.lock();
  if (!--thr_count)
    thr_wait.signal();
  thr_count_lock.unlock();
  cerr << "native_joinable exit." << endl;
  return 0;
}

extern "C"
void*
native_detached(void*)
{
  realthing_joinable* j= new realthing_joinable;
  int i=4;
  while (i--) {
    do_something();
  }
  j->join(0);
  thr_count_lock.lock();
  if (!--thr_count)
    thr_wait.signal();
  thr_count_lock.unlock();
  cerr << "native_detached exit." << endl;
  return 0;
}

#ifdef _MSC_VER
extern "C"
unsigned __stdcall nt_native_joinable(void*)
{
  (void) native_joinable(0);
  _endthreadex(0);
  return 0;
}

extern "C"
unsigned __stdcall nt_native_detached(void*)
{
  (void) native_detached(0);
  _endthread();
  return 0;
}

#endif


int
main(int argc,char** argv)
{
  long loop = 1;

  if (argc > 1) {
    loop = strtol(argv[1],0,10);
    if (!loop || loop == LONG_MAX || loop == LONG_MIN) {
      cerr << "usage: mix [<loop count > 0>]" << endl;
      return 1;
    }
  }

  while (loop--)
    {
      thr_count_lock.lock();
      // create two threads using the native thread system.
      // Wait on thr_wait until thr_count reaches 0.

      // XXX use the header file guard macro to determine what native thread
      //     system is in use. Bad.
#if defined(__omnithread_posix_h_)
      // only works for Draft 10 or the final standard.
      pthread_t x,y;
      pthread_attr_t attr;
      pthread_attr_init(&attr);
      if (pthread_create(&x,&attr,native_joinable,0) != 0 ||
	  pthread_create(&y,&attr,native_detached,0) != 0) {
	cerr << "Error: pthread_create failed." << endl;
	return 0;
      }
      thr_count += 2;
      pthread_detach(y);
      pthread_attr_destroy(&attr);
      while (thr_count) {
	thr_wait.wait();
      }
      pthread_join(x,0);
#elif defined(__omnithread_nt_h_)
      HANDLE x,y;
      unsigned int t;
      x = (HANDLE)_beginthreadex(
				 NULL,
				 0,
				 nt_native_joinable,
				 0,
				 CREATE_SUSPENDED, 
				 &t);

      y = (HANDLE)_beginthreadex(
				 NULL,
				 0,
				 nt_native_detached,
				 0,
				 CREATE_SUSPENDED, 
				 &t);

      if (!x || ResumeThread(x) == 0xffffffff) {
	cerr << "Error: cannot create a native thread." << endl;
	return 1;
      }

      if (!y || ResumeThread(y) == 0xffffffff) {
	cerr << "Error: cannot create a native thread." << endl;
	return 1;
      }
      thr_count += 2;

      while (thr_count) {
	thr_wait.wait();
      }

      if (WaitForSingleObject(x, INFINITE) != WAIT_OBJECT_0) {
	cerr << "Error: cannot join a native thread." << endl;
	return 1;
      }
      if (!CloseHandle(x)) {
	cerr << "Error: cannot close a native thread handle." << endl;
      }
      
#else
#error "What is the native thread system?"
#endif

      thr_count_lock.unlock();
      cerr << "main thread: all threads have exit" << endl;
    }
  cerr << "main thread: exit." << endl;
  return 0;
}


static omni_mutex     plock;
static omni_condition pcond(&plock);

static
void
do_something()
{
  int count = random_l() % 10 + 1;
  while (count--) {
    unsigned long abs_sec;
    unsigned long abs_nsec;
    plock.lock();
    omni_thread::get_time(&abs_sec,&abs_nsec,0,(random_l()%100+1)*1000000);
    pcond.timedwait(abs_sec,abs_nsec);
    plock.unlock();
    omni_thread::sleep(0,(random_l()%100+1)*1000000);
  }
}

-------------------------- end ---------------------------------------