[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 ---------------------------------------