Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

thread.H

Go to the documentation of this file.
00001 /*
00002  * Copyright 2000, Brown University, Providence, RI.
00003  * 
00004  *                         All Rights Reserved
00005  * 
00006  * Permission to use, copy, modify, and distribute this software and its
00007  * documentation for any purpose other than its incorporation into a
00008  * commercial product is hereby granted without fee, provided that the
00009  * above copyright notice appear in all copies and that both that
00010  * copyright notice and this permission notice appear in supporting
00011  * documentation, and that the name of Brown University not be used in
00012  * advertising or publicity pertaining to distribution of the software
00013  * without specific, written prior permission.
00014  * 
00015  * BROWN UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00016  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
00017  * PARTICULAR PURPOSE.  IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE FOR
00018  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00019  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00020  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00021  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00022  */
00023 
00024 #ifndef _JOT_STD_THREAD_H
00025 #define _JOT_STD_THREAD_H
00026 
00027 #include "std/dllimpexp.H"
00028 #include "std/config.H"
00029 #include "std/error.H"
00030 #include "std/thread_mutex.H"
00031 
00032 // This file should contain generalized thread support, but for now
00033 // it's just a pthread implmentation of a thread syncronization primitive.
00034 
00035 #ifdef USE_PTHREAD
00036 #if defined(sun) && !defined(_REENTRANT)
00037 // Would like to use #error, but that just gives a warning
00038 Need to compile thread stuff with -mt under Solaris
00039 #endif
00040 #include <pthread.h>
00041 
00042 class Thread {
00043    public:
00044       Thread()          { _running = false; }
00045       virtual ~Thread() { if (_running) pthread_cancel(_thread); }  
00046 
00047       void start()  { 
00048      pthread_attr_t attr;
00049          int retval;
00050      if ((retval = pthread_attr_init(&attr)) != 0) {
00051             err_sys("Thread:start - pthread_attr_init returned %d", retval);
00052          }
00053      if ((retval=pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0) {
00054             // On the SGI errno is cleared, so we have to use strerror
00055             err_quit("Thread:start - pthread_attr_setscope: %s", 
00056                      strerror(retval));
00057          }
00058      _running = !pthread_create(&_thread, &attr, kickstart, (void *)this);
00059      pthread_attr_destroy(&attr);
00060       }
00061    protected:
00062       virtual void threadProc() = 0;
00063 
00064    private:
00065       bool      _running;
00066       pthread_t _thread;
00067       static void *kickstart(void *me) { ((Thread *)me)->threadProc(); 
00068                                          return 0; }
00069 };
00070 
00071 
00072 class ThreadSync {
00073 private:
00074   pthread_mutex_t mut_;
00075   pthread_cond_t queue_;
00076   int count_;
00077   const int number_;
00078   int generation_;
00079 
00080 public:
00081   ThreadSync(int number): number_(number) {
00082     pthread_mutex_init(&mut_, 0);
00083     pthread_cond_init(&queue_, 0);
00084     count_ = 0;
00085     generation_ = 0;
00086   }
00087   
00088   ~ThreadSync() {
00089     pthread_mutex_destroy(&mut_);
00090     pthread_cond_destroy(&queue_);
00091   }
00092 
00093 #ifndef sgi 
00094   void wait() {
00095     pthread_mutex_lock(&mut_);
00096     if (++count_ < number_) {
00097       int my_generation = generation_;
00098       while(my_generation == generation_)
00099     pthread_cond_wait(&queue_, &mut_);
00100     } else {
00101       count_ = 0;
00102       generation_++;
00103       pthread_cond_broadcast(&queue_);
00104     }
00105     pthread_mutex_unlock(&mut_);
00106   }
00107 #else
00108   void wait() {
00109     pthread_mutex_lock(&mut_);
00110     if (++count_ < number_) {
00111       assert((count_ < number_) && (count_ > 0));
00112       int my_generation = generation_;
00113       pthread_mutex_unlock(&mut_);
00114       while(my_generation == generation_)
00115         ;
00116     } else {
00117       count_ = 0;
00118       generation_++;
00119       pthread_mutex_unlock(&mut_);
00120     }
00121   }
00122 #endif
00123 };
00124 
00125 class ThreadData {
00126    public:
00127       ThreadData()  : _key(0) { }
00128       // Call this only once after all threads are created
00129       void create() {
00130          if (pthread_key_create(&_key, 0)) {
00131             cerr << "ThreadData::create - Could not create key" << endl;
00132          }
00133       }
00134       // Call from threads
00135       void  set(void *val) { pthread_setspecific(_key, val);}
00136       void *get()          { return pthread_getspecific(_key);}
00137    protected:
00138       pthread_key_t _key;
00139 };
00140 #endif
00141 
00142 #endif

Generated on Mon Sep 15 16:25:57 2003 for gluebase by doxygen1.2.18