Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Thread.cc

Go to the documentation of this file.
00001 #ifndef PLATFORM_APERIOS
00002 #include "Thread.h"
00003 
00004 #include <pthread.h>
00005 #include <string.h>
00006 #include <iostream>
00007 #include <signal.h>
00008 #include <unistd.h>
00009 
00010 using namespace std;
00011 
00012 struct Threadstorage_t {
00013   Threadstorage_t() : threadInfo(), threadAttr() {
00014     if(int err=pthread_attr_init(&threadAttr))
00015       cerr << "Threadstorage_t constructor, pthread_attr_init: " << strerror(err) << endl;;
00016   }
00017   ~Threadstorage_t() {
00018     if(int err=pthread_attr_destroy(&threadAttr))
00019       cerr << "Threadstorage_t destructor, pthread_attr_destroy: " << strerror(err) << endl;
00020   }
00021   pthread_t threadInfo;
00022   pthread_attr_t threadAttr;
00023 private:
00024   Threadstorage_t(const Threadstorage_t& r); //!< don't call
00025   Threadstorage_t& operator=(const Threadstorage_t& r); //!< don't call
00026 };
00027 
00028 Thread::Thread() : pt(new Threadstorage_t), running(false), returnValue(NULL) {}
00029 
00030 Thread::~Thread() {
00031   //can only happen externally
00032   if(running) {
00033     stop();
00034     join();
00035   }
00036   if(pt==NULL) {
00037     std::cerr << "Thread storage already deleted!?!?!" << std::endl;
00038     *(int*)NULL=0xDEADDEAD;
00039   }
00040   delete pt;
00041   pt=NULL;
00042 }
00043 
00044 void Thread::start() {
00045   if(running) {
00046     std::cerr << "Thread::start() -- thread is already running!" << std::endl;
00047     std::cerr << "   make another instance if you want to run another copy of this thread" << std::endl;
00048     return;
00049   }
00050   running=true;
00051   if(int err=pthread_create(&pt->threadInfo, &pt->threadAttr, launch, this))
00052     cerr << "Thread start(), pthread_create: " << strerror(err) << endl;
00053 }
00054 
00055 void * Thread::run() {
00056   for(;;) {
00057     unsigned int sleeptime=runloop();
00058     if(sleeptime==-1U)
00059       return returnValue;
00060     usleep(sleeptime);
00061     testCancel();
00062   }
00063   return NULL; //never happens
00064 }
00065 
00066 void Thread::stop() {
00067   if(int err=pthread_cancel(pt->threadInfo))
00068     cerr << "Thread cancel(), pthread_cancel: " << strerror(err) << endl;
00069 }
00070 
00071 void Thread::kill() {
00072   if(int err=pthread_kill(pt->threadInfo,SIGALRM))
00073     cerr << "Thread stop(), pthread_kill(SIGALRM): " << strerror(err) << endl;
00074 }
00075 
00076 void Thread::murder() {
00077   if(int err=pthread_detach(pt->threadInfo))
00078     cerr << "Thread kill(), thread_detach: " << strerror(err) << endl;
00079   if(int err=pthread_kill(pt->threadInfo,SIGSTOP))
00080     cerr << "Thread kill(), pthread_kill(SIGSTOP): " << strerror(err) << endl;
00081   running=false;
00082 }
00083 
00084 void * Thread::join() {
00085   void * ans=NULL;
00086   if(int err=pthread_join(pt->threadInfo, &ans))
00087     cerr << "Thread join(), pthread_join: " << strerror(err) << endl;
00088   return ans;
00089 }
00090 
00091 void Thread::testCancel() {
00092   pthread_testcancel();
00093 }
00094 
00095 void * Thread::launch(void * msg) {
00096   if(int err=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL))
00097     cerr << "Thread launch(), pthread_setcanceltype: " << strerror(err) << endl;
00098   if(int err=pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL))
00099     cerr << "Thread launch(), pthread_setcanceltype: " << strerror(err) << endl;
00100   signal(SIGALRM,Thread::handle_signal);
00101   void * ans=NULL;
00102   {
00103     //These pthread functions actually define a scope between them
00104     //I've added braces of my own to make this explicitly clear
00105     pthread_cleanup_push(Thread::handle_exit,msg);
00106     static_cast<Thread*>(msg)->run();
00107     pthread_cleanup_pop(true);
00108   }
00109   return ans;
00110 }
00111 
00112 void Thread::handle_signal(int /*sig*/) {
00113   pthread_exit(NULL);
00114 }
00115 
00116 void Thread::handle_exit(void * th) {
00117   static_cast<Thread*>(th)->running=false;
00118 }
00119 
00120 namespace ThreadNS {
00121     
00122   struct LockStorage {
00123     LockStorage() : mutex(), attr() {
00124       pthread_mutexattr_init(&attr);
00125       pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
00126       pthread_mutex_init(&mutex,&attr);
00127     }
00128     ~LockStorage() {
00129       pthread_mutexattr_destroy(&attr);
00130       pthread_mutex_destroy(&mutex);
00131     }
00132     LockStorage(const LockStorage& ls) : mutex(ls.mutex), attr(ls.attr) {}
00133     LockStorage& operator=(const LockStorage& ls) { mutex=ls.mutex; attr=ls.attr; return *this; }
00134     void lock() {
00135       pthread_mutex_lock(&mutex);
00136     }
00137     bool trylock() {
00138       return !pthread_mutex_trylock(&mutex);
00139     }
00140     void unlock() {
00141       pthread_mutex_unlock(&mutex);
00142     }
00143     pthread_mutex_t mutex;
00144     pthread_mutexattr_t attr;
00145   };
00146 
00147   map<int,struct LockStorage*> Lock::ids;
00148   bool Lock::issetup=false;
00149 
00150   Lock::Lock() : my_id() {
00151     if(!issetup)
00152       setup();
00153     ids[-1]->lock();
00154     my_id=(--ids.end())->first+1;
00155     ids[my_id]=new LockStorage;
00156     ids[-1]->unlock();
00157   }
00158   /*
00159   Lock::Lock(int ident, bool autolock/ *=true* /) : my_id(ident) {
00160     if(!issetup)
00161       setup();
00162     if(ids.find(my_id)==ids.end()) {
00163       ids[-1]->lock();
00164       ids[my_id]=new LockStorage;
00165       ids[-1]->unlock();
00166     }
00167     if(autolock)
00168       ids[my_id]->lock();
00169   }
00170   */
00171   Lock::~Lock() {
00172     ids[my_id]->unlock();
00173   }
00174 
00175   void Lock::lock() {
00176     ids[my_id]->lock();
00177   }
00178   bool Lock::trylock() {
00179     return ids[my_id]->trylock();
00180   }
00181   void Lock::unlock() {
00182     ids[my_id]->unlock();
00183   }
00184   void Lock::setup() {
00185     issetup=true;
00186     ids[-1]=new LockStorage;
00187   }
00188 
00189 }
00190 
00191 #endif // PLATFORM check
00192 
00193 /*! @file
00194 * @brief Describes the Thread class and its AutoThread templated subclass
00195 * @author ejt (Creator)
00196 *
00197 * $Author: ejt $
00198 * $Name: tekkotsu-2_4_1 $
00199 * $Revision: 1.6 $
00200 * $State: Exp $
00201 * $Date: 2005/08/01 23:17:59 $
00202 */

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:49 2005 by Doxygen 1.4.4