00001 // @(#)root/thread:$Id: TCondition.cxx 29797 2009-08-17 14:35:51Z rdm $ 00002 // Author: Fons Rademakers 01/07/97 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 ////////////////////////////////////////////////////////////////////////// 00013 // // 00014 // TCondition // 00015 // // 00016 // This class implements a condition variable. Use a condition variable // 00017 // to signal threads. The actual work is done via the TConditionImp // 00018 // class (either TPosixCondition or TWin32Condition). // 00019 // // 00020 ////////////////////////////////////////////////////////////////////////// 00021 00022 #include "TCondition.h" 00023 #include "TMutex.h" 00024 #include "TThreadFactory.h" 00025 00026 00027 ClassImp(TCondition) 00028 00029 //______________________________________________________________________________ 00030 TCondition::TCondition(TMutex *m) 00031 { 00032 // Create a condition variable. The actual condition implementation 00033 // will be provided via the TThreadFactory. If no external mutex is 00034 // provided one will be created. Use GetMutex() to get this mutex 00035 // and use it before calling Signal() or Broadcast(). 00036 00037 fPrivateMutex = (m == 0); 00038 if (fPrivateMutex) { 00039 fMutex = new TMutex(); 00040 } else { 00041 fMutex = m; 00042 } 00043 00044 fConditionImp = gThreadFactory->CreateConditionImp(fMutex->fMutexImp); 00045 00046 if (!fConditionImp) 00047 Error("TCondition", "could not create TConditionImp"); 00048 } 00049 00050 //______________________________________________________________________________ 00051 TCondition::~TCondition() 00052 { 00053 // Clean up condition variable. 00054 00055 delete fConditionImp; 00056 if (fPrivateMutex) delete fMutex; 00057 } 00058 00059 //______________________________________________________________________________ 00060 TMutex *TCondition::GetMutex() const 00061 { 00062 // Get internally created mutex. Use it to lock resources 00063 // before calling Signal() or Broadcast(). Returns 0 if 00064 // external mutex was provided in TCondition ctor. 00065 00066 if (fPrivateMutex) 00067 return fMutex; 00068 return 0; 00069 } 00070 00071 //______________________________________________________________________________ 00072 Int_t TCondition::Wait() 00073 { 00074 // Wait to be signaled. 00075 00076 if (!fConditionImp) return -1; 00077 00078 Int_t iret; 00079 if (fPrivateMutex) fMutex->Lock(); 00080 iret = fConditionImp->Wait(); 00081 if (fPrivateMutex) fMutex->UnLock(); 00082 return iret; 00083 } 00084 00085 //______________________________________________________________________________ 00086 Int_t TCondition::TimedWait(ULong_t secs, ULong_t nanoSec) 00087 { 00088 // Wait to be signaled or till the timer times out. 00089 // This method is given an absolute time since the beginning of 00090 // the EPOCH (use TThread::GetTime() to get this absolute time). 00091 // To wait for a relative time from now, use 00092 // TCondition::TimedWaitRelative(ULong_t ms). 00093 // Returns 0 if successfully signalled, 1 if time expired and -1 in 00094 // case of error. 00095 00096 if (!fConditionImp) return -1; 00097 00098 Int_t iret; 00099 if (fPrivateMutex) fMutex->Lock(); 00100 iret = fConditionImp->TimedWait(secs, nanoSec); 00101 if (fPrivateMutex) fMutex->UnLock(); 00102 return iret; 00103 } 00104 00105 //______________________________________________________________________________ 00106 Int_t TCondition::TimedWaitRelative(ULong_t ms) 00107 { 00108 // Wait to be signaled or till the timer times out. 00109 // This method is given a relative time from now. 00110 // To wait for an absolute time since the beginning of the EPOCH, use 00111 // TCondition::TimedWait(ULong_t secs, ULong_t nanoSec). 00112 // Returns 0 if successfully signalled, 1 if time expired and -1 in 00113 // case of error. 00114 00115 if (!fConditionImp) return -1; 00116 00117 ULong_t absSec, absNanoSec; 00118 TThread::GetTime(&absSec, &absNanoSec); 00119 00120 ULong_t dsec = ms/1000; 00121 absSec += dsec; 00122 absNanoSec += (ms - dsec*1000) * 1000000; 00123 if (absNanoSec > 999999999) { 00124 absSec += 1; 00125 absNanoSec -= 1000000000; 00126 } 00127 00128 return TimedWait(absSec, absNanoSec); 00129 }