Thread.ccGo 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);
00025 Threadstorage_t& operator=(const Threadstorage_t& r);
00026 };
00027
00028 Thread::Thread() : pt(new Threadstorage_t), running(false), returnValue(NULL) {}
00029
00030 Thread::~Thread() {
00031
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;
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
00104
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 ) {
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
00160
00161
00162
00163
00164
00165
00166
00167
00168
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
00194
00195
00196
00197
00198
00199
00200
00201
00202
|