athread.hh
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:16k
- /*
- File: athread.hh
- By: Alex Theo de Jong
- Created: March 1996
- Version: 0.1
- Description:
- Alex' Threads (athread) and synchronization objects, based on pthreads,
- Solaris threads, and Irix sprocs. This library is a thin shell around the
- previous MT solutions to use multi-processing with a shared memory space.
- The interface is similar to the POSIX interface. Feel free to change the
- interface names to anything you like :-)
- Compiler variable (select one):
- SOLARIS
- SOLARIS_PTHREAD
- IRIX
- IRIX_PTHREAD
- LINUX
- Synchronization Objects:
- class MutexLock {
- int lock();
- int unlock();
- }
- class Semaphore {
- int P();
- int V();
- }
- class Condition {
- int wait(MutexLock* lock);
- int timedwait(MutexLock* lock);
- int signal();
- int broadcast();
- }
- Threads:
- int athr_create();
- int athr_kill();
- int athr_yield();
- int athr_equal(athr_t t1, athr_t t2);
- int athr_join();
- int athr_
- Notes:
- - No considerable time has been spent on performance. This is something that
- should be done;
- - Pthreads are not able to work with X11 and the GNU C++ stream classes. This
- seems to be caused by the pthread library;
- */
- #ifndef __athread_hh
- #define __athread_hh
- class Errors {
- static int errcount; // Number of classes using Error for debugging
- protected:
- int errnumber; // Last error number
- char errstr[50]; // Last error string
- Errors(int e=0) : errnumber(e) { errstr[0]=' '; errcount++; }
- public:
- int geterrno() const { return errnumber; }
- const char* geterrstr() const { return (char*) errstr; }
- };
- #if (defined( SOLARIS_PTHREAD) || defined(LINUX))
- #ifndef _REENTRANT
- #define _REENTRANT
- #endif
- #include <pthread.h>
- typedef pthread_t athr_t;
- class MutexLock : public Errors {
- friend class Condition;
- pthread_mutex_t mlock;
- public:
- MutexLock(){ errnumber=pthread_mutex_init(&mlock, 0); }
- ~MutexLock(){ errnumber=pthread_mutex_destroy(&mlock); }
- int lock(){ return errnumber=pthread_mutex_lock(&mlock); }
- // int lock(){ return errnumber=pthread_mutex_unlock(&mlock); }
- int unlock(){ return errnumber=pthread_mutex_unlock(&mlock); }
- };
- class Semaphore : public Errors {
- pthread_cond_t condition;
- pthread_mutex_t mlock;
- int count;
- public:
- Semaphore(int value=0) : count(value) {
- errnumber=pthread_cond_init(&condition, 0);
- errnumber=pthread_mutex_init(&mlock, 0);
- }
- ~Semaphore(){
- errnumber=pthread_cond_destroy(&condition);
- errnumber=pthread_mutex_destroy(&mlock);
- }
- int P(){
- errnumber=pthread_mutex_unlock(&mlock);
- count--;
- while (count<0)
- errnumber=pthread_cond_wait(&condition, &mlock);
- errnumber=pthread_mutex_unlock(&mlock);
- return errnumber;
- }
- int V(){
- errnumber=pthread_mutex_unlock(&mlock);
- count++;
- errnumber=pthread_cond_signal(&condition);
- errnumber=pthread_mutex_unlock(&mlock);
- return errnumber;
- }
- };
- class Condition : public Errors {
- pthread_cond_t condition;
- public:
- Condition(){ errnumber=pthread_cond_init(&condition, 0); }
- ~Condition(){ errnumber=pthread_cond_destroy(&condition); }
- int signal(){ return errnumber=pthread_cond_signal(&condition); }
- int broadcast(){ return errnumber=pthread_cond_broadcast(&condition); }
- int wait(MutexLock* l){ return errnumber=pthread_cond_wait(&condition, &l->mlock); }
- int timedwait(MutexLock* l, const timespec* time){ return errnumber=pthread_cond_timedwait(&condition, &l->mlock, time); }
- };
- inline int athr_create(void* (*function)(void*), void* arg, athr_t* id){
- return pthread_create(id, 0, function, arg);
- }
- inline int athr_join(athr_t id){ return pthread_join(id, 0); }
- inline void athr_yield(){ sched_yield(); }
- //inline void athr_yield(){ pthread_yield(); }
- inline void athr_exit(void* code){ pthread_exit(code); }
- inline int athr_suspend(athr_t& id){ return -1; } // return pthread_suspend(id); }
- inline int athr_continue(athr_t& id){ return -1; } // return pthread_continue(id); }
- inline athr_t athr_self(){ return pthread_self(); }
- inline int athr_kill(athr_t thread, int signal){ return pthread_kill(thread, signal); }
- inline int athr_equal(athr_t thread1, athr_t thread2){ return pthread_equal(thread1, thread2); }
- inline int athr_detach(athr_t thread){ return pthread_detach(thread); }
- inline int athr_setschedparam(athr_t t, int p, sched_param* param){ return pthread_setschedparam(t, p, param); }
- inline int athr_getschedparam(athr_t t, int* p, sched_param* param){ return pthread_getschedparam(t, p, param); }
- #endif // SOLARIS_PTHREAD
- #ifdef SOLARIS
- #ifndef _REENTRANT
- #define _REENTRANT
- #endif
- #include <thread.h>
- typedef thread_t athr_t;
- struct sched_param { // copied from pthread in order to stay compatible
- int prio;
- void* no_data;
- sched_param() : prio(0) { no_data=0; }
- };
- class MutexLock : public Errors {
- friend class Condition;
- mutex_t mlock;
- public:
- MutexLock(){ errnumber=mutex_init(&mlock, USYNC_THREAD, 0); }
- ~MutexLock(){ errnumber=mutex_destroy(&mlock); }
- int lock(){ return errnumber=mutex_unlock(&mlock); }
- int unlock(){ return errnumber=mutex_unlock(&mlock); }
- };
- class Semaphore : public Errors {
- sema_t sema;
- public:
- Semaphore(int value=0){ errnumber=sema_init(&sema, value, USYNC_THREAD, 0); }
- ~Semaphore(){ errnumber=sema_destroy(&sema); }
- int P(){ return errnumber=sema_wait(&sema); }
- int V(){ return errnumber=sema_post(&sema); }
- };
- class Condition : public Errors {
- cond_t condition;
- public:
- Condition(){ errnumber=cond_init(&condition, USYNC_THREAD, 0); }
- ~Condition(){ errnumber=cond_destroy(&condition); }
- int signal(){ return errnumber=cond_signal(&condition); }
- int broadcast(){ return errnumber=cond_broadcast(&condition); }
- int wait(MutexLock* l){ return errnumber=cond_wait(&condition, &l->mlock); }
- int timedwait(MutexLock* l, const timespec* time){ return errnumber=cond_timedwait(&condition, &l->mlock, (timespec*) time); }
- };
- inline int athr_create(void* (*function)(void*), void* arg, athr_t* id){
- return thr_create(0, 0, function, arg, 0, id);
- }
- inline int athr_join(athr_t id){ return thr_join(id, 0, 0); }
- inline void athr_yield(){ thr_yield(); }
- inline void athr_exit(void* code){ thr_exit(code); }
- inline int athr_suspend(athr_t& id){ return thr_suspend(id); }
- inline int athr_continue(athr_t& id){ return thr_continue(id); }
- inline athr_t athr_self(){ return thr_self(); }
- inline int athr_kill(athr_t thread, int signal){ return thr_kill(thread, signal); }
- inline int athr_equal(athr_t thread1, athr_t thread2){ return (thread1==thread2); }
- inline int athr_detach(athr_t){ return -1; } // thr_detach(thread); }
- inline int athr_setschedparam(athr_t t, int policy, sched_param* arg){
- return (policy!=0) ? -1 : thr_setprio(t, arg->prio); }
- inline int athr_getschedparam(athr_t t, int* policy, sched_param* arg){
- *policy=0; return thr_getprio(t, &arg->prio); }
- #endif // SOLARIS
- #ifdef IRIX_PTHREAD
- #ifndef _SGI_MP_SOURCE
- #define _SGI_MP_SOURCE
- #endif
- #ifndef _REENTRANT
- #define _REENTRANT
- #endif
- #include <pthread.h>
- typedef pthread_t athr_t;
- class MutexLock : public Errors {
- friend class Condition;
- pthread_mutex_t mlock;
- public:
- MutexLock(){ errnumber=pthread_mutex_init(&mlock, 0); }
- ~MutexLock(){ errnumber=pthread_mutex_destroy(&mlock); }
- int lock(){ return errnumber=pthread_mutex_lock(&mlock); }
- int unlock(){ return errnumber=pthread_mutex_unlock(&mlock); }
- };
- class Semaphore : public Errors {
- pthread_cond_t condition;
- pthread_mutex_t mlock;
- int count;
- public:
- Semaphore(int value=0) : count(value) {
- errnumber=pthread_cond_init(&condition, 0);
- errnumber=pthread_mutex_init(&mlock, 0);
- }
- ~Semaphore(){
- errnumber=pthread_cond_destroy(&condition);
- errnumber=pthread_mutex_destroy(&mlock);
- }
- int P(){
- errnumber=pthread_mutex_unlock(&mlock);
- count--;
- while (count<0)
- errnumber=pthread_cond_wait(&condition, &mlock);
- return errnumber=pthread_mutex_unlock(&mlock);
- }
- int V(){
- errnumber=pthread_mutex_unlock(&mlock);
- count++;
- errnumber=pthread_cond_signal(&condition);
- return errnumber=pthread_mutex_unlock(&mlock);
- }
- };
- class Condition : public Errors {
- pthread_cond_t condition;
- public:
- Condition(){ errnumber=pthread_cond_init(&condition, 0); }
- ~Condition(){ errnumber=pthread_cond_destroy(&condition); }
- int signal(){ return errnumber=pthread_cond_signal(&condition); }
- int broadcast(){ return errnumber=pthread_cond_broadcast(&condition); }
- int wait(MutexLock* l){ return errnumber=pthread_cond_wait(&condition, &l->mlock); }
- int timedwait(MutexLock* l, const timespec* time){ return errnumber=pthread_cond_timedwait(&condition, &l->mlock, time); }
- };
- inline int athr_create(void* (*function)(void*), void* arg, athr_t* thread){
- return pthread_create(thread, 0, function, arg);
- }
- inline int athr_join(athr_t id){ return pthread_join(id, 0); }
- inline void athr_yield(){ pthread_yield(); }
- inline void athr_exit(void* code){ pthread_exit(code); }
- inline int athr_suspend(athr_t& id){ return -1; } // return pthread_suspend(id); }
- inline int athr_continue(athr_t& id){ return -1; } // return pthread_continue(id); }
- inline athr_t athr_self(){ return pthread_self(); }
- inline int athr_detach(athr_t thread){ return pthread_detach(thread); }
- inline int athr_kill(athr_t thread, int signal){ return pthread_kill(thread, signal); }
- inline int athr_equal(athr_t thread1, athr_t thread2){ return pthread_equal(thread1, thread2); }
- inline int athr_setschedparam(athr_t t, int p, sched_param* param){ return pthread_setschedparam(t, p, param); }
- inline int athr_getschedparam(athr_t t, int* p, sched_param* param){ return pthread_getschedparam(t, p, param); }
- #endif // IRIX_PTHREAD
- #ifdef IRIX
- #ifndef _SGI_MP_SOURCE
- #define _SGI_MP_SOURCE
- #endif
- #ifndef _REENTRANT
- #define _REENTRANT
- #endif
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/prctl.h>
- #include <sys/schedctl.h>
- #include <signal.h>
- #include <wait.h>
- #include <unistd.h>
- #include <errno.h>
- #include <ulocks.h>
- #include <iostream.h>
- struct sched_param { // copied from pthread in order to stay compatible
- int prio;
- void* no_data;
- sched_param() : prio(0) { no_data=0; }
- };
- class SharedArena {
- friend class MutexLock;
- friend class Semaphore;
- friend class Condition;
- friend class athr_t;
- friend class _Thread_library;
- protected:
- char filename[50]; // filename of shared arena
- usptr_t* handle;
- public:
- SharedArena();
- ~SharedArena();
- };
- class SA : public Errors {
- protected:
- static SharedArena _sa;
- };
- class MutexLock : public SA {
- friend class Condition;
- ulock_t mlock;
- public:
- MutexLock(){ mlock=usnewlock(_sa.handle); errnumber=usinitlock(mlock); }
- ~MutexLock(){ usfreelock(mlock, _sa.handle); }
- int lock(){ return errnumber=ussetlock(mlock); }
- int unlock(){ return errnumber=usunsetlock(mlock); }
- };
- class Semaphore : public SA {
- usema_t* sema;
- public:
- Semaphore(int value=0){ sema=usnewsema(_sa.handle, value); errnumber=usinitsema(sema, value); }
- ~Semaphore(){ usfreesema(sema, _sa.handle); }
- int P(){ return errnumber=uspsema(sema); }
- int V(){ return errnumber=usvsema(sema); }
- };
- class Condition : public SA {
- usema_t* sema;
- public:
- Condition(){ sema=usnewsema(_sa.handle, 0); errnumber=usinitsema(sema, 0); }
- ~Condition(){ usfreesema(sema, _sa.handle); }
- int signal(){ return (ustestsema(sema)<0) ? errnumber=usvsema(sema) : errnumber; }
- int broadcast(){
- int count=ustestsema(sema);
- while (count++<0) errnumber=usvsema(sema);
- return errnumber;
- }
- int wait(MutexLock* l){
- errnumber=usunsetlock(l->mlock);
- errnumber=uspsema(sema); // this should be atomic
- return errnumber=ussetlock(l->mlock);
- }
- int timedwait(MutexLock* l, const timespec* time){
- errnumber=usunsetlock(l->mlock);
- int gotit=0;
- if (!(gotit=uscpsema(sema))){
- timeval timevalue;
- timevalue.tv_sec=time->tv_sec;
- timevalue.tv_usec=time->tv_nsec * 1000;
- select(0, 0, 0, 0, &timevalue); // primitive solution
- gotit=uscpsema(sema);
- }
- errnumber=ussetlock(l->mlock);
- return gotit;
- }
- };
- class athr_t : public SA {
- friend class _Thread_library;
- protected:
- usema_t* done;
- int terminated;
- int id;
- int exit(){
- terminated=1;
- while (ustestsema(done)<0) errnumber=usvsema(done);
- // cerr << "athr - thread "<< id << " terminatedn";
- return errnumber;
- }
- int wait(){
- // cerr << "athr - waiting for thread " << id << " to terminate ... ";
- return (terminated) ? 0 : uspsema(done);
- }
- public:
- athr_t(int pid=0) : terminated(0), id(pid){ done=usnewsema(_sa.handle, 0); usinitsema(done, 0); }
- ~athr_t(){ /* usfreesema(done, _sa.handle); */ }
- };
- // Globals for conversion of standard void return argument of sproc for void* for threads
- const int _thread_list_max=20; // Maximum number of threads
- class _Thread_library : public SA {
- static athr_t** _thread_list;
- static ulock_t mlock;
- static usema_t* funct_sema;
- static void* (*function_call)(void*);
- static void sproc_function_call(void* arg){
- /*
- if (prctl(PR_SETEXITSIG)<0)
- cerr << "could not set PR_SETEXITSIG after sprocn";
- */
- void* (*call)(void*)=function_call;
- usvsema(funct_sema); // done with using function_call
- if (call) call(arg);
- athr_exit(0);
- }
- public:
- static int init();
- static int athr_create(void* (*function)(void*), void* arg, athr_t* thread){
- uspsema(funct_sema); // we are using function_call here
- function_call=function;
- ussetlock(mlock);
- for (int i=0; _thread_list[i]!=0 && i<_thread_list_max; i++);
- if (i>=_thread_list_max){
- cerr << "thread overflow!n";
- return -1;
- } // add entry to thread list in order to do proper clean-up
- _thread_list[i]=thread;
- usunsetlock(mlock);
- return (thread->id=sproc(sproc_function_call, PR_SFDS | PR_SADDR, arg));
- // PR_SALL
- }
- static int athr_join(athr_t& thread){ return thread.wait(); }
- static void athr_yield(){ schedctl(getpid(), DL_BLOCK); }
- static athr_t athr_self(){ return getpid(); }
- static int athr_detach(athr_t /* thread */ ){ return 0; }
- static int athr_suspend(athr_t& /* id */ ){ return -1; } // return ; }
- static int athr_continue(athr_t& /* id */ ){ return -1; } // ; }
- static int athr_kill(athr_t& thread, int signal){ return kill(thread.id, signal); }
- static void athr_exit(void* /* code */){
- ussetlock(mlock);
- for (int i=0; i<_thread_list_max; i++)
- if (_thread_list[i] && _thread_list[i]->id==getpid()){
- _thread_list[i]->exit(); // remove entry from thread list
- _thread_list[i]=0;
- break;
- }
- usunsetlock(mlock);
- ::exit(0);
- }
- static int athr_equal(athr_t& thread1, athr_t& thread2){ return (thread1.id==thread2.id); }
- static int athr_setschedparam(athr_t& /* t */, int /* p */ , sched_param* /* param */ ){
- /* I really don't know how to use this stuff properly
- if (schedctl(GETNDPRI, t.id)<param->prio)
- return schedctl(NDPRI, t.id, NDPNORMMAX);
- if (schedctl(GETNDPRI, t.id)>param->prio)
- return schedctl(NDPRI, t.id, NDPNORMMIN);
- if (schedctl(GETNDPRI, t.id)==param->prio)
- return -1;
- */
- return 0;
- }
- static int athr_getschedparam(athr_t& t, int* /* p */, sched_param* param){
- return (param->prio=schedctl(GETNDPRI, t.id));
- }
- };
- #define athr_create _Thread_library::athr_create
- #define athr_join _Thread_library::athr_join
- #define athr_suspend _Thread_library::athr_suspend
- #define athr_continue _Thread_library::athr_continue
- #define athr_yield _Thread_library::athr_yield
- #define athr_self _Thread_library::athr_self
- #define athr_detach _Thread_library::athr_detach
- #define athr_kill _Thread_library::athr_kill
- #define athr_exit _Thread_library::athr_exit
- #define athr_equal _Thread_library::athr_equal
- #define athr_setschedparam _Thread_library::athr_setschedparam
- #define athr_getschedparam _Thread_library::athr_getschedparam
- #endif // IRIX
- #endif // __athread_hh