Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

thread.H

Go to the documentation of this file.
00001 
00002 #ifndef _JOT_STD_THREAD_H
00003 #define _JOT_STD_THREAD_H
00004 #include "std/support.H"
00005 #include "thread_mutex.H"
00006 
00007 // This file should contain generalized thread support, but for now
00008 // it's just a pthread implmentation of a thread syncronization primitive.
00009 
00010 #ifdef USE_PTHREAD
00011 #if defined(sun) && !defined(_REENTRANT)
00012 // Would like to use #error, but that just gives a warning
00013 Need to compile thread stuff with -mt under Solaris
00014 #endif
00015 #include <pthread.h>
00016 
00017 class Thread {
00018    public:
00019       Thread()          { _running = false; }
00020       virtual ~Thread() { if (_running) pthread_cancel(_thread); }  
00021 
00022       void start()  { 
00023     pthread_attr_t attr;
00024          int retval;
00025     if ((retval = pthread_attr_init(&attr)) != 0) 
00026     {
00027       err_msg("Thread:start - pthread_attr_init returned %d: %s", retval,strerror(errno));
00028       exit(1);
00029     }
00030     if ((retval=pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0) 
00031     {
00032       // On the SGI errno is cleared, so we have to use strerror
00033       err_msg("Thread:start - pthread_attr_setscope: %s", strerror(retval));
00034       exit(1);
00035     }
00036     _running = !pthread_create(&_thread, &attr, kickstart, (void *)this);
00037     pthread_attr_destroy(&attr);
00038       }
00039    protected:
00040       virtual void threadProc() = 0;
00041 
00042    private:
00043       bool      _running;
00044       pthread_t _thread;
00045       static void *kickstart(void *me) { ((Thread *)me)->threadProc(); 
00046                                          return 0; }
00047 };
00048 
00049 
00050 class ThreadSync {
00051 private:
00052   pthread_mutex_t mut_;
00053   pthread_cond_t queue_;
00054   int count_;
00055   const int number_;
00056   int generation_;
00057 
00058 public:
00059   ThreadSync(int number): number_(number) {
00060     pthread_mutex_init(&mut_, 0);
00061     pthread_cond_init(&queue_, 0);
00062     count_ = 0;
00063     generation_ = 0;
00064   }
00065   
00066   ~ThreadSync() {
00067     pthread_mutex_destroy(&mut_);
00068     pthread_cond_destroy(&queue_);
00069   }
00070 
00071 #ifndef sgi 
00072   void wait() {
00073     pthread_mutex_lock(&mut_);
00074     if (++count_ < number_) {
00075       int my_generation = generation_;
00076       while(my_generation == generation_)
00077    pthread_cond_wait(&queue_, &mut_);
00078     } else {
00079       count_ = 0;
00080       generation_++;
00081       pthread_cond_broadcast(&queue_);
00082     }
00083     pthread_mutex_unlock(&mut_);
00084   }
00085 #else
00086   void wait() {
00087     pthread_mutex_lock(&mut_);
00088     if (++count_ < number_) {
00089       assert((count_ < number_) && (count_ > 0));
00090       int my_generation = generation_;
00091       pthread_mutex_unlock(&mut_);
00092       while(my_generation == generation_)
00093         ;
00094     } else {
00095       count_ = 0;
00096       generation_++;
00097       pthread_mutex_unlock(&mut_);
00098     }
00099   }
00100 #endif
00101 };
00102 
00103 class ThreadData {
00104    public:
00105       ThreadData()  : _key(0) { }
00106       // Call this only once after all threads are created
00107       void create() {
00108          if (pthread_key_create(&_key, 0)) {
00109             cerr << "ThreadData::create - Could not create key" << endl;
00110          }
00111       }
00112       // Call from threads
00113       void  set(void *val) { pthread_setspecific(_key, val);}
00114       void *get()          { return pthread_getspecific(_key);}
00115    protected:
00116       pthread_key_t _key;
00117 };
00118 #endif
00119 #endif

Generated on Mon Sep 18 11:39:34 2006 for jot by  doxygen 1.4.4