athread.hh
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:16k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.    File: athread.hh
  3.    By: Alex Theo de Jong
  4.    Created: March 1996
  5.    Version: 0.1
  6.    Description:
  7.    Alex' Threads (athread) and synchronization objects, based on pthreads, 
  8.    Solaris threads, and Irix sprocs. This library is a thin shell around the 
  9.    previous MT solutions to use multi-processing with a shared memory space. 
  10.    The interface is similar to the POSIX interface. Feel free to change the 
  11.    interface names to anything you like :-)
  12.    Compiler variable (select one):
  13.      SOLARIS
  14.      SOLARIS_PTHREAD
  15.      IRIX
  16.      IRIX_PTHREAD
  17.      LINUX
  18.    Synchronization Objects:
  19.      class MutexLock {
  20.        int lock();
  21.        int unlock();
  22.      }
  23.      class Semaphore {
  24.        int P();
  25.        int V();
  26.      }
  27.      class Condition {
  28.        int wait(MutexLock* lock);
  29.        int timedwait(MutexLock* lock);
  30.        int signal();
  31.        int broadcast();
  32.      }
  33.    Threads:
  34.      int athr_create();
  35.      int athr_kill();
  36.      int athr_yield();
  37.      int athr_equal(athr_t t1, athr_t t2);
  38.      int athr_join();
  39.      int athr_
  40.    Notes:
  41.    - No considerable time has been spent on performance. This is something that
  42.      should be done;
  43.    - Pthreads are not able to work with X11 and the GNU C++ stream classes. This
  44.      seems to be caused by the pthread library; 
  45. */
  46. #ifndef __athread_hh
  47. #define __athread_hh
  48. class Errors {
  49.   static int errcount;        // Number of classes using Error for debugging
  50.  protected:
  51.   int errnumber;              // Last error number
  52.   char errstr[50];            // Last error string
  53.   Errors(int e=0) : errnumber(e) { errstr[0]=''; errcount++; }
  54.  public:
  55.   int geterrno() const { return errnumber; }
  56.   const char* geterrstr() const { return (char*) errstr; }
  57. };
  58. #if (defined( SOLARIS_PTHREAD) || defined(LINUX)) 
  59. #ifndef _REENTRANT
  60. #define _REENTRANT
  61. #endif
  62. #include <pthread.h>
  63. typedef pthread_t athr_t;
  64. class MutexLock : public Errors {
  65.   friend class Condition;
  66.   pthread_mutex_t mlock;
  67.  public:
  68.   MutexLock(){ errnumber=pthread_mutex_init(&mlock, 0); }
  69.   ~MutexLock(){ errnumber=pthread_mutex_destroy(&mlock); }
  70.   int lock(){ return errnumber=pthread_mutex_lock(&mlock); }
  71. //  int lock(){ return errnumber=pthread_mutex_unlock(&mlock); }  
  72.   int unlock(){ return errnumber=pthread_mutex_unlock(&mlock); }
  73. };
  74. class Semaphore : public Errors {
  75.   pthread_cond_t condition;
  76.   pthread_mutex_t mlock;
  77.   int count;
  78.  public:
  79.   Semaphore(int value=0) : count(value) {
  80.     errnumber=pthread_cond_init(&condition, 0); 
  81.     errnumber=pthread_mutex_init(&mlock, 0); 
  82.   }
  83.   ~Semaphore(){
  84.     errnumber=pthread_cond_destroy(&condition); 
  85.     errnumber=pthread_mutex_destroy(&mlock);
  86.   }
  87.   int P(){
  88.     errnumber=pthread_mutex_unlock(&mlock);
  89.     count--;
  90.     while (count<0)
  91.       errnumber=pthread_cond_wait(&condition, &mlock);
  92.     errnumber=pthread_mutex_unlock(&mlock);
  93.     return errnumber; 
  94.   }
  95.   int V(){ 
  96.     errnumber=pthread_mutex_unlock(&mlock);
  97.     count++;
  98.     errnumber=pthread_cond_signal(&condition);
  99.     errnumber=pthread_mutex_unlock(&mlock);
  100.     return errnumber;
  101.   }
  102. };
  103. class Condition : public Errors {
  104.   pthread_cond_t condition;
  105.  public:
  106.   Condition(){ errnumber=pthread_cond_init(&condition, 0); }
  107.   ~Condition(){ errnumber=pthread_cond_destroy(&condition); }
  108.   int signal(){ return errnumber=pthread_cond_signal(&condition); }
  109.   int broadcast(){ return errnumber=pthread_cond_broadcast(&condition); }
  110.   int wait(MutexLock* l){ return errnumber=pthread_cond_wait(&condition, &l->mlock); }
  111.   int timedwait(MutexLock* l, const timespec* time){ return errnumber=pthread_cond_timedwait(&condition, &l->mlock, time); }
  112. };
  113. inline int athr_create(void* (*function)(void*), void* arg, athr_t* id){
  114.   return pthread_create(id, 0, function, arg);
  115. }
  116. inline int athr_join(athr_t id){ return pthread_join(id, 0); }
  117. inline void athr_yield(){ sched_yield(); }
  118. //inline void athr_yield(){ pthread_yield(); }
  119. inline void athr_exit(void* code){ pthread_exit(code); }
  120. inline int athr_suspend(athr_t& id){ return -1; }  // return pthread_suspend(id); }
  121. inline int athr_continue(athr_t& id){ return -1; } // return pthread_continue(id); }
  122. inline athr_t athr_self(){ return pthread_self(); }
  123. inline int athr_kill(athr_t thread, int signal){ return pthread_kill(thread, signal); }
  124. inline int athr_equal(athr_t thread1, athr_t thread2){ return pthread_equal(thread1, thread2); }
  125. inline int athr_detach(athr_t thread){ return pthread_detach(thread); }
  126. inline int athr_setschedparam(athr_t t, int p, sched_param* param){ return pthread_setschedparam(t, p, param); }
  127. inline int athr_getschedparam(athr_t t, int* p, sched_param* param){ return pthread_getschedparam(t, p, param); }
  128. #endif // SOLARIS_PTHREAD
  129. #ifdef SOLARIS
  130. #ifndef _REENTRANT
  131. #define _REENTRANT
  132. #endif
  133. #include <thread.h>
  134. typedef thread_t athr_t;
  135. struct sched_param {   // copied from pthread in order to stay compatible
  136.   int prio;
  137.   void* no_data;
  138.   sched_param() : prio(0) { no_data=0; }
  139. };
  140. class MutexLock : public Errors {
  141.   friend class Condition;
  142.   mutex_t mlock;
  143.  public:
  144.   MutexLock(){ errnumber=mutex_init(&mlock, USYNC_THREAD, 0); }
  145.   ~MutexLock(){ errnumber=mutex_destroy(&mlock); }
  146.   int lock(){ return errnumber=mutex_unlock(&mlock); }
  147.   int unlock(){ return errnumber=mutex_unlock(&mlock); }
  148. };
  149. class Semaphore : public Errors {
  150.   sema_t sema;
  151.  public:
  152.   Semaphore(int value=0){ errnumber=sema_init(&sema, value, USYNC_THREAD, 0); }
  153.   ~Semaphore(){ errnumber=sema_destroy(&sema); }
  154.   int P(){ return errnumber=sema_wait(&sema); }
  155.   int V(){ return errnumber=sema_post(&sema); }
  156. };
  157. class Condition : public Errors {
  158.   cond_t condition;
  159.  public:
  160.   Condition(){ errnumber=cond_init(&condition, USYNC_THREAD, 0); }
  161.   ~Condition(){ errnumber=cond_destroy(&condition); }
  162.   int signal(){ return errnumber=cond_signal(&condition); }
  163.   int broadcast(){ return errnumber=cond_broadcast(&condition); }
  164.   int wait(MutexLock* l){ return errnumber=cond_wait(&condition, &l->mlock); }
  165.   int timedwait(MutexLock* l, const timespec* time){ return errnumber=cond_timedwait(&condition, &l->mlock, (timespec*) time); }
  166. };
  167. inline int athr_create(void* (*function)(void*), void* arg, athr_t* id){
  168.   return thr_create(0, 0, function, arg, 0, id);
  169. }
  170. inline int athr_join(athr_t id){ return thr_join(id, 0, 0); }
  171. inline void athr_yield(){ thr_yield(); }
  172. inline void athr_exit(void* code){ thr_exit(code); }
  173. inline int athr_suspend(athr_t& id){ return thr_suspend(id); }
  174. inline int athr_continue(athr_t& id){ return thr_continue(id); }
  175. inline athr_t athr_self(){ return thr_self(); }
  176. inline int athr_kill(athr_t thread, int signal){ return thr_kill(thread, signal); }
  177. inline int athr_equal(athr_t thread1, athr_t thread2){ return (thread1==thread2); }
  178. inline int athr_detach(athr_t){ return -1; } // thr_detach(thread); }
  179. inline int athr_setschedparam(athr_t t, int policy, sched_param* arg){ 
  180.   return (policy!=0) ? -1 : thr_setprio(t, arg->prio); }
  181. inline int athr_getschedparam(athr_t t, int* policy, sched_param* arg){
  182.   *policy=0; return thr_getprio(t, &arg->prio); }
  183. #endif // SOLARIS
  184. #ifdef IRIX_PTHREAD
  185. #ifndef _SGI_MP_SOURCE
  186. #define _SGI_MP_SOURCE
  187. #endif
  188. #ifndef _REENTRANT
  189. #define _REENTRANT
  190. #endif
  191. #include <pthread.h>
  192. typedef pthread_t athr_t;
  193. class MutexLock : public Errors {
  194.   friend class Condition;
  195.   pthread_mutex_t mlock;
  196.  public:
  197.   MutexLock(){ errnumber=pthread_mutex_init(&mlock, 0); }
  198.   ~MutexLock(){ errnumber=pthread_mutex_destroy(&mlock); }
  199.   int lock(){ return errnumber=pthread_mutex_lock(&mlock); }
  200.   int unlock(){ return errnumber=pthread_mutex_unlock(&mlock); }
  201. };
  202. class Semaphore : public Errors {
  203.   pthread_cond_t condition;
  204.   pthread_mutex_t mlock;
  205.   int count;
  206.  public:
  207.   Semaphore(int value=0) : count(value) { 
  208.     errnumber=pthread_cond_init(&condition, 0); 
  209.     errnumber=pthread_mutex_init(&mlock, 0); 
  210.   }
  211.   ~Semaphore(){
  212.     errnumber=pthread_cond_destroy(&condition); 
  213.     errnumber=pthread_mutex_destroy(&mlock);
  214.   }
  215.   int P(){
  216.     errnumber=pthread_mutex_unlock(&mlock);
  217.     count--;
  218.     while (count<0)
  219.       errnumber=pthread_cond_wait(&condition, &mlock);
  220.     return errnumber=pthread_mutex_unlock(&mlock);
  221.   }
  222.   int V(){ 
  223.     errnumber=pthread_mutex_unlock(&mlock);
  224.     count++;
  225.     errnumber=pthread_cond_signal(&condition);
  226.     return errnumber=pthread_mutex_unlock(&mlock);
  227.   }
  228. };
  229. class Condition : public Errors {
  230.   pthread_cond_t condition;
  231.  public:
  232.   Condition(){ errnumber=pthread_cond_init(&condition, 0); }
  233.   ~Condition(){ errnumber=pthread_cond_destroy(&condition); }
  234.   int signal(){ return errnumber=pthread_cond_signal(&condition); }
  235.   int broadcast(){ return errnumber=pthread_cond_broadcast(&condition); }
  236.   int wait(MutexLock* l){ return errnumber=pthread_cond_wait(&condition, &l->mlock); }
  237.   int timedwait(MutexLock* l, const timespec* time){ return errnumber=pthread_cond_timedwait(&condition, &l->mlock, time); }
  238. };
  239. inline int athr_create(void* (*function)(void*), void* arg, athr_t* thread){
  240.   return pthread_create(thread, 0, function, arg);
  241. }
  242. inline int athr_join(athr_t id){ return pthread_join(id, 0); }
  243. inline void athr_yield(){ pthread_yield(); }
  244. inline void athr_exit(void* code){ pthread_exit(code); }
  245. inline int athr_suspend(athr_t& id){  return -1; } // return pthread_suspend(id); }
  246. inline int athr_continue(athr_t& id){ return -1; } // return pthread_continue(id); }
  247. inline athr_t athr_self(){ return pthread_self(); }
  248. inline int athr_detach(athr_t thread){ return pthread_detach(thread); }
  249. inline int athr_kill(athr_t thread, int signal){ return pthread_kill(thread, signal); }
  250. inline int athr_equal(athr_t thread1, athr_t thread2){ return pthread_equal(thread1, thread2); }
  251. inline int athr_setschedparam(athr_t t, int p, sched_param* param){ return pthread_setschedparam(t, p, param); }
  252. inline int athr_getschedparam(athr_t t, int* p, sched_param* param){ return pthread_getschedparam(t, p, param); }
  253. #endif // IRIX_PTHREAD
  254. #ifdef IRIX
  255. #ifndef _SGI_MP_SOURCE
  256. #define _SGI_MP_SOURCE
  257. #endif
  258. #ifndef _REENTRANT
  259. #define _REENTRANT
  260. #endif
  261. #include <sys/time.h>
  262. #include <sys/types.h>
  263. #include <sys/prctl.h>
  264. #include <sys/schedctl.h>
  265. #include <signal.h>
  266. #include <wait.h>
  267. #include <unistd.h>
  268. #include <errno.h>
  269. #include <ulocks.h>
  270. #include <iostream.h>
  271. struct sched_param {   // copied from pthread in order to stay compatible
  272.   int prio;
  273.   void* no_data;
  274.   sched_param() : prio(0) { no_data=0; }
  275. };
  276. class SharedArena {
  277.   friend class MutexLock;
  278.   friend class Semaphore;
  279.   friend class Condition;
  280.   friend class athr_t;
  281.   friend class _Thread_library;
  282.  protected:
  283.   char filename[50];  // filename of shared arena
  284.   usptr_t* handle;
  285.  public:
  286.   SharedArena();
  287.   ~SharedArena();
  288. };
  289. class SA : public Errors {
  290.  protected:
  291.   static SharedArena _sa;
  292. };
  293. class MutexLock : public SA {
  294.   friend class Condition;
  295.   ulock_t mlock;
  296.  public:
  297.   MutexLock(){ mlock=usnewlock(_sa.handle); errnumber=usinitlock(mlock); }
  298.   ~MutexLock(){ usfreelock(mlock, _sa.handle); }
  299.   int lock(){ return errnumber=ussetlock(mlock); }
  300.   int unlock(){ return errnumber=usunsetlock(mlock); }
  301. };
  302. class Semaphore :  public SA {
  303.   usema_t* sema;
  304.  public:
  305.   Semaphore(int value=0){ sema=usnewsema(_sa.handle, value); errnumber=usinitsema(sema, value); }
  306.   ~Semaphore(){ usfreesema(sema, _sa.handle); }
  307.   int P(){ return errnumber=uspsema(sema); }
  308.   int V(){ return errnumber=usvsema(sema); }
  309. };
  310. class Condition : public SA {
  311.   usema_t* sema;
  312.  public:
  313.   Condition(){ sema=usnewsema(_sa.handle, 0); errnumber=usinitsema(sema, 0); }
  314.   ~Condition(){ usfreesema(sema, _sa.handle); }
  315.   int signal(){ return (ustestsema(sema)<0) ? errnumber=usvsema(sema) : errnumber; }
  316.   int broadcast(){
  317.     int count=ustestsema(sema);
  318.     while (count++<0) errnumber=usvsema(sema); 
  319.     return errnumber;
  320.   }
  321.   int wait(MutexLock* l){
  322.     errnumber=usunsetlock(l->mlock); 
  323.     errnumber=uspsema(sema);     // this should be atomic
  324.     return errnumber=ussetlock(l->mlock);
  325.   }
  326.   int timedwait(MutexLock* l, const timespec* time){ 
  327.     errnumber=usunsetlock(l->mlock); 
  328.     int gotit=0;
  329.     if (!(gotit=uscpsema(sema))){
  330.       timeval timevalue;
  331.       timevalue.tv_sec=time->tv_sec;
  332.       timevalue.tv_usec=time->tv_nsec * 1000;
  333.       select(0, 0, 0, 0, &timevalue);  // primitive solution 
  334.       gotit=uscpsema(sema);
  335.     }
  336.     errnumber=ussetlock(l->mlock); 
  337.     return gotit;
  338.   }
  339. };
  340. class athr_t : public SA {
  341.   friend class _Thread_library;
  342.  protected:
  343.   usema_t* done;
  344.   int terminated;
  345.   int id;
  346.   int exit(){
  347.     terminated=1;
  348.     while (ustestsema(done)<0) errnumber=usvsema(done); 
  349. //    cerr << "athr - thread "<< id << " terminatedn";
  350.     return errnumber;
  351.   }
  352.   int wait(){
  353. //    cerr << "athr - waiting for thread " << id << " to terminate ... ";
  354.     return (terminated) ? 0 : uspsema(done);
  355.   }
  356.  public:
  357.   athr_t(int pid=0) : terminated(0), id(pid){ done=usnewsema(_sa.handle, 0); usinitsema(done, 0); }
  358.   ~athr_t(){ /*  usfreesema(done, _sa.handle); */ }
  359. };
  360. // Globals for conversion of standard void return argument of sproc for void* for threads
  361. const int _thread_list_max=20;  // Maximum number of threads
  362. class _Thread_library : public SA {
  363.   static athr_t** _thread_list;
  364.   static ulock_t mlock;
  365.   static usema_t* funct_sema;
  366.   static void* (*function_call)(void*);
  367.   static void sproc_function_call(void* arg){
  368. /*
  369.     if (prctl(PR_SETEXITSIG)<0)
  370.       cerr << "could not set PR_SETEXITSIG after sprocn";
  371. */
  372.     void* (*call)(void*)=function_call;
  373.     usvsema(funct_sema);  // done with using function_call
  374.     if (call) call(arg);
  375.     athr_exit(0);
  376.   }
  377.  public:
  378.   static int init();
  379.   static int athr_create(void* (*function)(void*), void* arg, athr_t* thread){
  380.     uspsema(funct_sema);   // we are using function_call here
  381.     function_call=function;
  382.     ussetlock(mlock);
  383.     for (int i=0; _thread_list[i]!=0 && i<_thread_list_max; i++);
  384.     if (i>=_thread_list_max){
  385.       cerr << "thread overflow!n";
  386.       return -1;
  387.     }                         // add entry to thread list in order to do proper clean-up
  388.     _thread_list[i]=thread;
  389.     usunsetlock(mlock);
  390.     return (thread->id=sproc(sproc_function_call, PR_SFDS | PR_SADDR, arg)); 
  391.     // PR_SALL
  392.   }
  393.   static int athr_join(athr_t& thread){ return thread.wait(); }
  394.   static void athr_yield(){ schedctl(getpid(), DL_BLOCK); }
  395.   static athr_t athr_self(){ return getpid(); }
  396.   static int athr_detach(athr_t /* thread */ ){ return 0; }
  397.   static int athr_suspend(athr_t& /* id */ ){  return -1; } // return ; }
  398.   static int athr_continue(athr_t& /* id */ ){ return -1; } // ; }
  399.   static int athr_kill(athr_t& thread, int signal){ return kill(thread.id, signal); }
  400.   static void athr_exit(void* /* code */){
  401.     ussetlock(mlock);
  402.     for (int i=0; i<_thread_list_max; i++)
  403.       if (_thread_list[i] && _thread_list[i]->id==getpid()){
  404. _thread_list[i]->exit();      // remove entry from thread list
  405. _thread_list[i]=0;
  406. break;
  407.       }
  408.     usunsetlock(mlock);
  409.     ::exit(0);
  410.   }
  411.   static int athr_equal(athr_t& thread1, athr_t& thread2){ return (thread1.id==thread2.id); }
  412.   static int athr_setschedparam(athr_t& /* t */, int /* p */ , sched_param* /* param */ ){ 
  413. /* I really don't know how to use this stuff properly
  414.     if (schedctl(GETNDPRI, t.id)<param->prio)
  415.       return schedctl(NDPRI, t.id, NDPNORMMAX);
  416.     if (schedctl(GETNDPRI, t.id)>param->prio)
  417.       return schedctl(NDPRI, t.id, NDPNORMMIN);
  418.     if (schedctl(GETNDPRI, t.id)==param->prio)
  419.     return -1;
  420. */
  421.     return 0;
  422.   }
  423.   static int athr_getschedparam(athr_t& t, int* /* p */, sched_param* param){
  424.     return (param->prio=schedctl(GETNDPRI, t.id));
  425.   }
  426. };
  427. #define athr_create        _Thread_library::athr_create
  428. #define athr_join          _Thread_library::athr_join
  429. #define athr_suspend       _Thread_library::athr_suspend
  430. #define athr_continue      _Thread_library::athr_continue
  431. #define athr_yield         _Thread_library::athr_yield
  432. #define athr_self          _Thread_library::athr_self
  433. #define athr_detach        _Thread_library::athr_detach
  434. #define athr_kill          _Thread_library::athr_kill
  435. #define athr_exit          _Thread_library::athr_exit
  436. #define athr_equal         _Thread_library::athr_equal
  437. #define athr_setschedparam _Thread_library::athr_setschedparam
  438. #define athr_getschedparam _Thread_library::athr_getschedparam
  439. #endif // IRIX
  440. #endif // __athread_hh