00001 #ifndef PLATFORM_APERIOS
00002 #include "Thread.h"
00003 #include "Shared/ReferenceCounter.h"
00004 #include "ProcessID.h"
00005 #include "Shared/StackTrace.h"
00006 #include "Shared/MarkScope.h"
00007 
00008 #include <pthread.h>
00009 #include <string.h>
00010 #include <iostream>
00011 #include <signal.h>
00012 #include <unistd.h>
00013 #include <cassert>
00014 #include <cstdio>
00015 #include <errno.h>
00016 #include <stdexcept>
00017 
00018 using namespace std;
00019 
00020 #define THREADCANCEL_SANITY_CHECKS
00021 
00022 
00023 
00024 struct Threadstorage_t {
00025 
00026   Threadstorage_t() : threadInfo(), hasThread(false) {}
00027   
00028 
00029   pthread_t threadInfo;
00030 
00031 
00032   bool hasThread;
00033   
00034 
00035   static pthread_key_t selfKey;
00036 private:
00037   Threadstorage_t(const Threadstorage_t& r); 
00038   Threadstorage_t& operator=(const Threadstorage_t& r); 
00039 };
00040 static const pthread_key_t INVALID_THREADKEY=(pthread_key_t)-1;
00041 pthread_key_t Threadstorage_t::selfKey=INVALID_THREADKEY;
00042 
00043 
00044 void* Thread::CANCELLED = PTHREAD_CANCELED;
00045 
00046 Thread::Thread()
00047   : pt(new Threadstorage_t), started(false), running(false), exited(false), returnValue(NULL),
00048   noCancelDepth(0), 
00049 #ifndef USE_SIGNAL_TO_CANCEL_THREAD
00050   reqIntrDepth(0),
00051 #endif
00052   cancelOrig(PTHREAD_CANCEL_ENABLE), cancelRequested(false), cancelInProgress(false),
00053   group(NULL), startTrace(NULL), startLock(), stopLock()
00054 {
00055   Thread* cur=getCurrent();
00056   if(cur!=NULL)
00057     group=cur->getGroup();
00058 }
00059 
00060 Thread::~Thread() {
00061   startLock.lock();
00062   if(started && this!=getCurrent()) {
00063     stop();
00064     join();
00065   }
00066   
00067 
00068 
00069 
00070   assert(pt!=NULL);
00071   if(pt->hasThread) {
00072     if(int err=pthread_detach(pt->threadInfo)) {
00073       cerr << "~Thread(), thread_detach: " << strerror(err) << endl;
00074       stacktrace::displayStackTrace(startTrace);
00075     }
00076     pt->hasThread=false;
00077   }
00078   delete pt;
00079   pt=NULL;
00080   if(startTrace!=NULL)
00081     stacktrace::freeStackTrace(startTrace);
00082 }
00083 
00084 void Thread::start() {
00085   MarkScope sl(startLock);
00086   if(started) {
00087     std::cerr << "Thread::start() -- thread is already started!\n"
00088     "   Make another instance if you want to run another copy of this thread\n"
00089     "   ** Original start:" << std::endl;
00090     stacktrace::displayStackTrace(startTrace);
00091     std::cerr << "   ** Duplicate start:" << std::endl;
00092     stacktrace::displayCurrentStackTrace();
00093     return;
00094   }
00095   if(startTrace!=NULL)
00096     stacktrace::freeStackTrace(startTrace);
00097   startTrace = stacktrace::recordStackTrace();
00098   exited=cancelRequested=false;
00099   started=true;
00100   pthread_attr_t   threadAttributes;
00101   if(int err = pthread_attr_init(&threadAttributes))
00102     cerr << "Thread start(), could not init stack attributes: " << strerror(err) << endl;
00103   const size_t REQ_STACK = 2*1024*1024; 
00104   size_t stackSize=0;
00105   if(int err = pthread_attr_getstacksize(&threadAttributes, &stackSize)) 
00106     cerr << "Thread start(), get stack size: " << strerror(err) << endl;
00107   if(stackSize < REQ_STACK) {
00108     if(int err = pthread_attr_setstacksize(&threadAttributes, REQ_STACK)) 
00109       cerr << "Thread start(), set stack size: " << strerror(err) << endl;
00110   }
00111   if(pt->hasThread) {
00112     if(int err=pthread_detach(pt->threadInfo))
00113       cerr << "Thread start(), thread_detach of previous thread: " << strerror(err) << endl;
00114     pt->hasThread=false;
00115   }
00116   if(int err=pthread_create(&pt->threadInfo, &threadAttributes, launch, this))
00117     cerr << "Thread start(), pthread_create: " << strerror(err) << endl;
00118   else
00119     pt->hasThread=true;
00120 }
00121 
00122 void * Thread::run() {
00123   for(;;) {
00124     unsigned int sleeptime=runloop();
00125     if(sleeptime==-1U)
00126       return returnValue;
00127     if(sleeptime>0)
00128       usleep(sleeptime);
00129     testCancel();
00130   }
00131   
00132   return returnValue; 
00133 }
00134 
00135 Thread& Thread::interrupt() {
00136   if(!isRunning()) 
00137     return *this;
00138   struct sigaction sa;
00139   sa.sa_handler = handleInterrupt;
00140   if(sigemptyset(&sa.sa_mask)!=0)
00141     perror("Thread::interrupt(): clearing signal set via sigemptyset()");
00142   sa.sa_flags = 0;
00143   if(sigaction(SIGALRM,&sa,NULL)!=0)
00144     perror("Thread::interrupt(): installing interrupt handler via sigaction()");
00145   sendSignal(SIGALRM);
00146   return *this;
00147 }
00148 
00149 Thread& Thread::stop() {
00150   MarkScope l(stopLock);
00151   if(exited)
00152     return *this;
00153   if(!started && !running) {
00154     std::cerr << "Thread::stop() -- thread has not been started!" << std::endl;
00155     dereference();  
00156     
00157     return *this;
00158   }
00159 #ifdef USE_PTHREAD_CANCEL
00160   if(started && !running)
00161     usleep(50000);
00162   if(started && !running)
00163     std::cerr << "Thread::stop(): Waiting for thread launch to complete (stillborn thread?)" << std::endl;
00164   while(started && !running)
00165     usleep(100000);
00166   if(!running)
00167     return *this;
00168   if(int err=pthread_cancel(pt->threadInfo))
00169     cerr << "Thread cancel(), pthread_cancel("<<pt->threadInfo<<"): " << strerror(err) << endl;
00170 #else
00171   
00172   cancelRequested=true;
00173 #endif
00174 #ifdef USE_SIGNAL_TO_CANCEL_THREAD
00175 #  ifndef USE_PTHREAD_CANCEL
00176   
00177   if(!running)
00178     return *this;
00179 #  endif
00180   if(noCancelDepth>0)
00181     return *this;
00182   interrupt(); 
00183 #else
00184   if(reqIntrDepth>0)
00185     interrupt();
00186 #endif
00187   return *this;
00188 }
00189 
00190 Thread& Thread::kill() {
00191   sendSignal(SIGUSR1);
00192   return *this;
00193 }
00194 
00195 Thread& Thread::murder() {
00196   if(pt->hasThread) {
00197     if(int err=pthread_detach(pt->threadInfo))
00198       cerr << "Thread kill(), thread_detach: " << strerror(err) << endl;
00199     pt->hasThread=false;
00200   }
00201   sendSignal(SIGSTOP);
00202   started=running=false;
00203   exited=true;
00204   return *this;
00205 }
00206 
00207 void Thread::sendSignal(int sig) {
00208   if(started && !running)
00209     usleep(50000);
00210   if(started && !running)
00211     std::cerr << "Thread::stop(): Waiting for thread launch to complete (stillborn thread?)" << std::endl;
00212   while(started && !running)
00213     usleep(100000);
00214   if(!isRunning())
00215     return;
00216   if(int err=pthread_kill(pt->threadInfo,sig))
00217     if(err!=ESRCH) 
00218       cerr << "Thread sendSignal(), pthread_kill("<<sig<<"): " << strerror(err) << endl;
00219 }
00220 
00221 void * Thread::join() const {
00222   MarkScope l(startLock);
00223   if(!started || !pt->hasThread) 
00224     return cancelRequested ? CANCELLED : returnValue;
00225   void * ans=NULL;
00226   pthread_t cur = pt->threadInfo;
00227   pt->hasThread = false; 
00228   if(int err=pthread_join(cur, &ans)) {
00229     cerr << "thread join() returned " << err << " " << strerror(err) << endl;
00230     if((err==EINVAL || err==ESRCH) && (!started || !pthread_equal(cur, pt->threadInfo))) 
00231       return cancelRequested ? CANCELLED : returnValue;
00232     cerr << "Thread join() " << err << " (" << EINVAL << ',' << ESRCH << "), pthread_join: " << strerror(err) << endl;
00233     stacktrace::displayCurrentStackTrace();
00234   }
00235   return ans;
00236 }
00237 
00238 Thread* Thread::getCurrent() {
00239   if(Threadstorage_t::selfKey==INVALID_THREADKEY) {
00240     static bool gaveError=false;
00241     if(!gaveError) {
00242       cerr << "ERROR: In Thread::getCurrent(), selfKey uninitialized; Thread::initMainThread was not called." << endl;
00243       cerr << "       (This error will only be displayed once)" << endl;
00244       gaveError=true;
00245     }
00246     return NULL;
00247   }
00248   return static_cast< Thread* >(pthread_getspecific(Threadstorage_t::selfKey));
00249 }
00250 
00251 void Thread::initMainThread() {
00252   if(int err=pthread_key_create(&Threadstorage_t::selfKey,warnSelfUndestructed))
00253     cerr << "WARNING: In Thread::initMainThread(), pthread_key_create(selfKey) returned " << strerror(err) << endl;
00254   if(int err=pthread_setspecific(Threadstorage_t::selfKey,NULL))
00255     cerr << "WARNING: In Thread::initMainThread(), pthread_setspecific(selfKey) returned " << strerror(err) << endl;
00256 }
00257 
00258 void Thread::releaseMainThread() {
00259   
00260   if(Threadstorage_t::selfKey==INVALID_THREADKEY)
00261     return;
00262   if(int err=pthread_key_delete(Threadstorage_t::selfKey))
00263     cerr << "WARNING: In Thread::releaseMainThread, pthread_key_delete(selfKey) returned " << strerror(err) << endl;
00264 }
00265 
00266 void Thread::testCurrentCancel() {
00267   Thread * cur = getCurrent();
00268   if(cur==NULL) { 
00269 #ifdef USE_PTHREAD_CANCEL
00270     pthread_testcancel();
00271 #endif
00272     return;
00273   }
00274 #ifdef DEBUG
00275   if(cur->noCancelDepth!=0) {
00276     cerr << "WARNING: Thread::testCancel called with noCancelDepth=="<<cur->noCancelDepth<<" (process="<<ProcessID::getID()<<", thread="<<pthread_self()<<")"<<endl;
00277     cerr << "The thread was started at:" << endl;
00278     stacktrace::displayStackTrace(cur->startTrace);
00279     cerr << "The testCancel call is from:" << endl;
00280     stacktrace::displayCurrentStackTrace();
00281   }
00282 #endif
00283   if(cur->noCancelDepth!=0 || cur->cancelInProgress)
00284     return;
00285 #ifdef USE_PTHREAD_CANCEL
00286   cur->cancelInProgress=true; 
00287   pthread_testcancel();
00288   cur->cancelInProgress=false; 
00289 #else
00290   if(cur->cancelRequested) {
00291     cur->cancelInProgress=true; 
00292     throw cancellation_exception();
00293   }
00294 #endif
00295 }
00296 
00297 void * Thread::launch(void * msg) {
00298   
00299   Thread* cur=static_cast<Thread*>(msg);
00300   if(cur==NULL) {
00301     cerr << "ERROR: Thread::launch with NULL msg" << endl;
00302     return NULL;
00303   }
00304 
00305   if(int err=pthread_setspecific(Threadstorage_t::selfKey,msg))
00306     cerr << "WARNING: In Thread::launch(), pthread_setspecific(selfKey) returned " << strerror(err) << endl;
00307   
00308   cur->cancelInProgress=false;
00309   
00310   
00311   if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL))
00312     cerr << "Thread launch(), pthread_setcanceltype: " << strerror(err) << endl;
00313   ++(cur->noCancelDepth);
00314   if(signal(SIGUSR1,Thread::handle_launch_signal)==SIG_ERR)
00315     perror("Thread launch(), signal(SIGUSR1,handle_launch_signal)");
00316   cur->running=true;
00317   if(!cur->launched()) {
00318     
00319     --(cur->noCancelDepth);
00320     handle_exit(NULL);
00321     return cur->returnValue;
00322   }
00323   --(cur->noCancelDepth);
00324   
00325   
00326   
00327   cur->returnValue=CANCELLED; 
00328   
00329   
00330   
00331   pthread_cleanup_push(Thread::handle_exit,msg); {
00332     
00333     if(signal(SIGUSR1,Thread::handle_signal)==SIG_ERR)
00334       perror("Thread launch(), signal(SIGUSR1,handle_signal)");
00335     
00336     try {
00337       if(cur->noCancelDepth==0) {
00338         
00339         if(int err=pthread_setcancelstate(cur->cancelOrig,NULL))
00340           cerr << "Thread launch(), pthread_setcancelstate: " << strerror(err) << endl;
00341         if(int err=pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL))
00342           cerr << "Thread launch(), pthread_setcanceltype: " << strerror(err) << endl;
00343         cur->testCancel();
00344       }
00345       cur->returnValue=cur->run();
00346     } catch(const Thread::cancellation_exception&) {
00347       
00348       
00349     }
00350     
00351 
00352 
00353 
00354 
00355 
00356     
00357   } pthread_cleanup_pop(true);
00358   return cur->returnValue;
00359 }
00360 
00361 void Thread::handle_launch_signal(int ) {
00362   handle_exit(NULL);
00363   pthread_exit(NULL);
00364 }
00365 
00366 void Thread::handle_signal(int ) {
00367   pthread_exit(NULL);
00368 }
00369 
00370 void Thread::handle_exit(void * th) {
00371   
00372   Thread* cur=getCurrent();
00373   if(cur==NULL) {
00374     cerr << "ERROR: handle_exit called for a NULL thread" << endl;
00375     if(th!=NULL) {
00376       static_cast<Thread*>(th)->cancelled();
00377       static_cast<Thread*>(th)->started=static_cast<Thread*>(th)->running=false;
00378     }
00379     return;
00380   }
00381   
00382   { 
00383     MarkScope l(cur->stopLock);
00384     if(th!=NULL && th!=cur)
00385       cerr << "WARNING: handle_exit argument does not match selfKey" << endl;
00386     if(cur->noCancelDepth!=0) {
00387       cerr << "WARNING: thread " << pthread_self() << " of ProcessID_t " << ProcessID::getID() << " exited while noCancelDepth>0 (was " << cur->noCancelDepth << ")" << endl;
00388       cerr << "         This may indicate a mutex was left locked." << endl;
00389       cur->noCancelDepth=0; 
00390     }
00391     if(int err=pthread_setspecific(Threadstorage_t::selfKey,NULL))
00392       cerr << "WARNING: In Thread::handle_exit(), pthread_setspecific(selfKey) returned " << err << endl;
00393     cur->cancelled();
00394     cur->started=cur->running=false;
00395     cur->exited=true;
00396   }
00397   cur->dereference();
00398 }
00399 
00400 void Thread::pushNoCancel() {
00401   Thread * cur=getCurrent();
00402   if(cur==NULL) {
00403     
00404     
00405     if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL))
00406       cerr << "ERROR: Thread pushNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00407   } else {
00408     ++(cur->noCancelDepth);
00409     int previous=-1;
00410     if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&previous))
00411       cerr << "ERROR: Thread pushNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00412 #ifdef THREADCANCEL_SANITY_CHECKS
00413     if(cur->noCancelDepth==1 && previous!=cur->cancelOrig)
00414       cerr << "WARNING: In Thread::pushNoCancel, cancel state was wrong (was " << previous << ", expected " << cur->cancelOrig << ")" << endl;
00415     else if(cur->noCancelDepth!=1 && previous!=PTHREAD_CANCEL_DISABLE)
00416       cerr << "WARNING: In Thread::pushNoCancel, cancel state was somehow re-enabled" << endl;
00417 #endif
00418   }
00419 }
00420 void Thread::popNoCancel(bool doTestCancel) {
00421   Thread * cur=getCurrent();
00422   if(cur==NULL) {
00423     
00424     
00425     return; 
00426   } else if(cur->noCancelDepth==0) {
00427     cerr << "ERROR: Thread::popNoCancel underflow" << endl;
00428   } else
00429     --(cur->noCancelDepth);
00430   int previous=-1;
00431   if(cur->noCancelDepth==0) {
00432     if(int err=pthread_setcancelstate(cur->cancelOrig,&previous))
00433       cerr << "ERROR: Thread popNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00434     if(cur->cancelOrig==PTHREAD_CANCEL_ENABLE && doTestCancel)
00435       cur->testCancel(); 
00436   }
00437 #ifdef THREADCANCEL_SANITY_CHECKS
00438   else { 
00439     if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&previous))
00440       cerr << "ERROR: Thread popNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00441   }
00442   if(previous!=PTHREAD_CANCEL_DISABLE)
00443     cerr << "WARNING: In Thread::popNoCancel, cancel state was somehow re-enabled" << endl;
00444 #endif
00445 }
00446 
00447 void Thread::requestInterruptOnCancel() {
00448 #ifndef USE_SIGNAL_TO_CANCEL_THREAD
00449   Thread * cur=getCurrent();
00450   if(cur==NULL)
00451     return; 
00452   pushNoCancel();
00453   ++(cur->reqIntrDepth);
00454 #ifdef DEBUG
00455   if(cur->reqIntrDepth!=1)
00456     std::cerr << "WARNING: recursive Thread::requestInterruptOnCancel() " << cur->reqIntrDepth << std::endl;
00457 #endif
00458 #endif
00459 }
00460   
00461 void Thread::unrequestInterruptOnCancel() {
00462 #if !defined(USE_SIGNAL_TO_CANCEL_THREAD) || !defined(USE_TESTCANCEL_IN_INTERRUPT)
00463   Thread * cur=getCurrent();
00464   if(cur==NULL)
00465     return; 
00466 #endif
00467 #ifndef USE_SIGNAL_TO_CANCEL_THREAD
00468   if(cur->reqIntrDepth==0) {
00469     cerr << "ERROR: Thread::unrequestInterruptOnCancel underflow" << endl;
00470   } else {
00471     --(cur->reqIntrDepth);
00472   }
00473   popNoCancel();
00474 #endif
00475 #ifndef USE_TESTCANCEL_IN_INTERRUPT
00476   if(cur->noCancelDepth==0)
00477     cur->testCancel();
00478 #endif
00479 }
00480 
00481 void Thread::handleInterrupt(int ) {
00482   
00483   
00484   Thread * cur=Thread::getCurrent();
00485   if(cur==NULL) {
00486     
00487     
00488     
00489     return;
00490   }
00491 #ifdef USE_TESTCANCEL_IN_INTERRUPT
00492   if(cur->noCancelDepth==0)
00493     cur->testCancel();
00494 #endif
00495   cur->interrupted();
00496 }
00497 
00498 void Thread::warnSelfUndestructed(void* msg) {
00499   cerr << "ERROR: Thread local data (selfKey) not deleted by Thread::handle_exit" << endl;
00500   Thread* cur = getCurrent();
00501   if(cur!=NULL)
00502     cerr << "       Weird, key wasn't cleared... (" << cur << ") " << cur->noCancelDepth << " locks on stack? " << endl;;
00503   if(msg==NULL) {
00504     cerr << "       Message is null, warnCancelDepthUndestructed shouldn't have been called." << endl;
00505   } else {
00506     if(cur!=NULL && cur!=msg)
00507       cerr << "       and current thread does not match msg (" << cur << " vs " << msg << ")" << endl;
00508     cur = static_cast<Thread*>(msg);
00509   }
00510   if(cur!=NULL) {
00511     
00512     if(cur->noCancelDepth==0) {
00513       cerr << "       But at least the depth is 0" << endl;
00514     } else {
00515       cerr << "       The depth indicates there may be " << cur->noCancelDepth << " locks left in place" << endl;
00516     }
00517     cur->cancelled();
00518     cur->started=cur->running=false;
00519     pthread_setspecific(Threadstorage_t::selfKey,NULL);
00520   }
00521 }
00522 
00523 
00524 
00525 
00526 class Thread::Lock::LockStorage : public ReferenceCounter {
00527   friend class Thread::Condition;
00528 public:
00529 
00530   LockStorage() : ReferenceCounter(), locklevel(0), mutex(), attr(), threadkey() {
00531     addReference();
00532     pthread_mutexattr_init(&attr);
00533     pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
00534     pthread_mutex_init(&mutex,&attr);
00535   }
00536 
00537   ~LockStorage() {
00538     pthread_mutexattr_destroy(&attr);
00539     pthread_mutex_destroy(&mutex);
00540     if(locklevel>1) 
00541       cerr << "WARNING: lockstorage destructed with " << locklevel << " locks still in effect" << endl;
00542     while(locklevel>0) {
00543       locklevel--;
00544       Thread::popNoCancel(false); 
00545     }
00546   }
00547 
00548   LockStorage(const LockStorage& ls) : ReferenceCounter(ls), locklevel(ls.locklevel), mutex(ls.mutex), attr(ls.attr), threadkey(ls.threadkey) {}
00549 
00550   LockStorage& operator=(const LockStorage& ls) { ReferenceCounter::operator=(ls); locklevel=ls.locklevel; mutex=ls.mutex; attr=ls.attr; threadkey=ls.threadkey; return *this; }
00551   
00552 
00553   void lock() {
00554     if(int err=pthread_mutex_lock(&mutex)) {
00555       cerr << "ERROR: Thread::Lock::lock() failed: " << strerror(err) << endl;
00556     } else {
00557       locklevel++;
00558     }
00559   }
00560 
00561   bool trylock() {
00562     if(!pthread_mutex_trylock(&mutex)) {
00563       locklevel++;
00564       return true;
00565     } else {
00566       return false;
00567     }
00568   }
00569 
00570   void unlock() {
00571     if(locklevel==0) {
00572       cerr << "ERROR: Thread::Lock::unlock() underflow" << endl;
00573       stacktrace::displayCurrentStackTrace();
00574     }
00575     locklevel--;
00576     if(int err=pthread_mutex_unlock(&mutex))
00577       cerr << "ERROR: Thread::Lock::unlock() failed: " << strerror(err) << endl;
00578   }
00579 
00580   unsigned int getLockLevel() { return locklevel; }
00581   
00582 protected:
00583   unsigned int locklevel; 
00584   pthread_mutex_t mutex; 
00585   pthread_mutexattr_t attr; 
00586   pthread_key_t threadkey; 
00587 };
00588 
00589 Thread::Lock::LockStorage* Thread::Lock::glock=NULL;
00590 
00591 
00592 Thread::Lock::Lock() : mylock(new LockStorage), locklevel(0) {
00593   if(glock==NULL)
00594     setup();
00595 }
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 Thread::Lock::~Lock() {
00627   glock->lock();
00628   if(locklevel>1)
00629     cerr << "WARNING: Thread::Lock destructed with "<<locklevel<<" locks still in effect" << endl;
00630   if(!mylock->removeReference()) {
00631     std::cerr << "Lock was deleted with external reference?" << std::endl;
00632     stacktrace::displayCurrentStackTrace();
00633     while(locklevel>0)
00634       unlock();
00635   }
00636   mylock=NULL;
00637   glock->unlock();
00638 }
00639 
00640 void Thread::Lock::useResource(Resource::Data&) {
00641   mylock->lock();
00642   locklevel++;
00643 }
00644 bool Thread::Lock::trylock() {
00645   Thread::pushNoCancel();
00646   if(mylock->trylock()) {
00647     locklevel++;
00648     return true;
00649   } else {
00650     Thread::popNoCancel();
00651     return false;
00652   }
00653 }
00654 void Thread::Lock::releaseResource(Resource::Data&) {
00655   locklevel--;
00656   mylock->unlock();
00657 }
00658 unsigned int Thread::Lock::getLockLevel() const {
00659   return mylock->getLockLevel();
00660 }
00661 void Thread::Lock::setup() {
00662   if(glock==NULL)
00663     glock=new LockStorage;
00664 }
00665 
00666 
00667 
00668 
00669 class Thread::Condition::ConditionStorage {
00670 public:
00671 
00672   ConditionStorage() : cond() {
00673     if(int err=pthread_cond_init(&cond,NULL)) {
00674       cerr << "ERROR: Thread::Condition::ConditionStorage() failed: " << strerror(err) << endl;
00675     }
00676   }
00677 
00678   ~ConditionStorage() {
00679     if(int err=pthread_cond_destroy(&cond)) {
00680       cerr << "ERROR: Thread::Condition::~ConditionStorage() failed: " << strerror(err) << endl;
00681     }
00682   }
00683 
00684   pthread_cond_t cond;
00685 };
00686 
00687 
00688 Thread::Condition::Condition() : mycond(new ConditionStorage) {}
00689 Thread::Condition::~Condition() { delete mycond; mycond=NULL; }
00690 
00691 void Thread::Condition::broadcast() const {
00692   if(int err=pthread_cond_broadcast(&mycond->cond)) {
00693     cerr << "ERROR: Thread::Condition::broadcast() failed: " << strerror(err) << endl;
00694   }
00695 }
00696 void Thread::Condition::signal() const {
00697   if(int err=pthread_cond_signal(&mycond->cond)) {
00698     cerr << "ERROR: Thread::Condition::signal() failed: " << strerror(err) << endl;
00699   }
00700 }
00701 bool Thread::Condition::timedwait(Lock& l, const timespec* abstime, bool noWarn) const {
00702 #ifdef USE_SIGNAL_TO_CANCEL_THREAD
00703   Thread::testCurrentCancel();
00704 #endif
00705   unsigned int locklevel=l.mylock->locklevel;
00706   if(locklevel==1) {
00707     
00708   } else if(locklevel>1) {
00709     if(!noWarn)
00710       displayRecursiveLockWarning("timedwait",locklevel);
00711     while(l.mylock->locklevel>1)
00712       l.mylock->unlock();
00713   } else { 
00714     throw std::logic_error("Thread::Condition::timedwait() called without holding lock");
00715   }
00716   if(int err=pthread_cond_timedwait(&mycond->cond,&l.mylock->mutex,abstime)) {
00717     if(err!=ETIMEDOUT)
00718       cerr << "ERROR: Thread::Condition::timedwait() failed: " << strerror(err) << endl;
00719     while(l.mylock->locklevel<locklevel)
00720       l.mylock->lock();
00721     return false;
00722   }
00723   while(l.getLockLevel()<locklevel)
00724     l.mylock->lock();
00725 #ifdef USE_SIGNAL_TO_CANCEL_THREAD
00726   Thread::testCurrentCancel();
00727 #endif
00728   return true;
00729 }
00730 void Thread::Condition::wait(Lock& l, bool noWarn) const {
00731 #ifdef USE_SIGNAL_TO_CANCEL_THREAD
00732   Thread::testCurrentCancel();
00733 #endif
00734   unsigned int locklevel=l.mylock->locklevel;
00735   if(locklevel==1) {
00736     
00737   } else if(locklevel>1) {
00738     if(!noWarn)
00739       displayRecursiveLockWarning("wait",locklevel);
00740     while(l.mylock->locklevel>1)
00741       l.mylock->unlock();
00742   } else { 
00743     throw std::logic_error("Thread::Condition::wait() called without holding lock");
00744   }
00745   if(int err=pthread_cond_wait(&mycond->cond,&l.mylock->mutex)) {
00746     cerr << "ERROR: Thread::Condition::wait() failed: " << strerror(err) << endl;
00747   }
00748   while(l.getLockLevel()<locklevel)
00749     l.mylock->lock();
00750 #ifdef USE_SIGNAL_TO_CANCEL_THREAD
00751   Thread::testCurrentCancel();
00752 #endif
00753 }
00754 
00755 void Thread::Condition::displayRecursiveLockWarning(const char * fn, unsigned int locklevel) {
00756   std::cerr << "WARNING: Thread::Condition::"<<fn<<"() called holding a recursive lock. (depth " << locklevel << ")\n"
00757   "  You should verify outer lock scopes are safe to temporarily free during wait,\n"
00758   "  then pass 'true' for the noWarn argument to timedwait() to disable this message." << std::endl;
00759   stacktrace::displayCurrentStackTrace();
00760 }
00761 
00762 
00763 #endif // PLATFORM check
00764 
00765 
00766 
00767 
00768