00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "TGo4Thread.h"
00015
00016 #include "TThread.h"
00017 #include "TSystem.h"
00018 #include "TCondition.h"
00019
00020 #include "TGo4Runnable.h"
00021 #include "TGo4Log.h"
00022 #include "TGo4LockGuard.h"
00023 #include "Go4Exceptions.h"
00024
00025 TGo4Thread::TGo4Thread(const TGo4Thread &right)
00026 :TNamed(right)
00027 {
00028 GO4TRACE((14,"TGo4Thread::TGo4Thread() copy constructor",__LINE__, __FILE__));
00029 fxRunnable = right.fxRunnable;
00030 fbIsInternal = right.fbIsInternal;
00031 fxCondition = new TCondition();
00032 }
00033
00034 TGo4Thread::TGo4Thread (const char* name, TGo4Runnable* runnable, Bool_t internal)
00035 :TNamed(name,"This is a TGo4Thread"),
00036 fbIsCreated(kFALSE),
00037 fbIsRunning(kFALSE),
00038 fiThreadPID(0),
00039 fiThreadSelfID(0),
00040 fbIsWaiting(kFALSE),
00041 fxThread(0)
00042 {
00043 GO4TRACE((14,"TGo4Thread::TGo4Thread(const char*, TGo4Runnable*, Bool_t) constructor",__LINE__, __FILE__));
00044
00045 TGo4Log::Debug(" New Go4Thread ``%s'' created ",name);
00046 fxRunnable = runnable;
00047 fbIsInternal = internal;
00048 fxCondition = new TCondition();
00049 fxRunnable->SetThread(this);
00050 }
00051
00052
00053 TGo4Thread::~TGo4Thread()
00054 {
00055 GO4TRACE((14,"TGo4Thread::~TGo4Thread() destructor",__LINE__, __FILE__));
00056
00057 Stop();
00058 Cancel();
00059 delete fxCondition;
00060 if(fbIsInternal)
00061 {
00062 GO4TRACE((14,"TGo4Thread::~TGo4Thread() internal mode",__LINE__, __FILE__));
00063 TGo4Log::Debug(" Go4Thread ``%s'' deleting runnable ``%s'' ",
00064 GetName(),fxRunnable->GetName());
00065 delete fxRunnable;
00066 }
00067 else
00068 {
00069 GO4TRACE((14,"TGo4Thread::~TGo4Thread() non internal mode",__LINE__, __FILE__));
00070
00071 }
00072
00073 }
00074
00075 void TGo4Thread::Threadfunc (void* arg)
00076 {
00077 GO4TRACE((2,"TGo4Thread::Threadfunc(void*)",__LINE__, __FILE__));
00078 TGo4Thread* go4th= (TGo4Thread*) arg;
00079 TGo4Runnable* runnable = go4th->GetRunnable();
00080
00081
00082
00083 go4th->SetPID();
00084 go4th->SetSelfID();
00085
00086
00087 TGo4Log::Debug(" TThread %d (PID:%d) of Go4Thread ``%s'' started... \n",
00088 go4th->GetSelfID(), go4th->GetPID(), go4th->GetName());
00089
00090 for(;;)
00091 {
00092 try
00093 {
00094 GO4TRACE((1,"TGo4Thread::Threadfunc(void*) try block",__LINE__, __FILE__));
00095 while(1)
00096 {
00097 TThread::CancelPoint();
00098 if( !(go4th->IsRunning()) )
00099 {
00100 GO4TRACE((1,"TGo4Thread::Threadfunc(void*) waiting mode",__LINE__, __FILE__));
00101 TGo4Log::Debug(" Go4Thread ``%s'' (PID:%d) waiting...\n",
00102 go4th->GetName(), go4th->GetPID());
00103 go4th->SetWaiting(kTRUE);
00104 go4th->GetCondition()->Wait();
00105 go4th->SetWaiting(kFALSE);
00106 TGo4Log::Debug(" Go4Thread ``%s'' (PID:%d) running...\n",
00107 go4th->GetName(), go4th->GetPID() );
00108 }
00109 else
00110 {
00111
00112 }
00113
00114 if(go4th->IsCreated())
00115
00116 {
00117 GO4TRACE((1,"TGo4Thread::Threadfunc(void*) entering running mode",__LINE__, __FILE__));
00118
00119 runnable->PreRun((void*) 0);
00120 while(go4th->IsRunning())
00121 {
00122 TThread::CancelPoint();
00123 runnable->Run((void*) 0);
00124 }
00125
00126 runnable->PostRun((void*) 0);
00127
00128 }
00129 else
00130
00131 {
00132 GO4TRACE((1,"TGo4Thread::Threadfunc(void*) entering Cancel loop",__LINE__, __FILE__));
00133 TGo4Log::Debug(" Go4Thread ``%s'' entering Cancel loop\n ", go4th->GetName());
00134 while(!(go4th->IsCreated()))
00135 {
00136 {
00137 #ifdef WIN32
00138 return;
00139 #endif
00140 GO4TRACE((1,"TGo4Thread::Threadfunc(void*) in Cancel loop",__LINE__, __FILE__));
00141 Sleep(500);
00142 TThread::CancelPoint();
00143 }
00144 }
00145 }
00146 }
00147 }
00148 catch(TGo4Exception& ex)
00149 {
00150 GO4TRACE((1,"TGo4Thread::Threadfunc(void*) Go4Exception Catch",__LINE__, __FILE__));
00151 runnable->ThreadCatch(ex);
00152 TThread::CancelPoint();
00153 }
00154
00155 catch(...)
00156 {
00157 GO4TRACE((1,"TGo4Thread::Threadfunc(void*) Unexpected Catch",__LINE__, __FILE__));
00158
00159 TThread::CancelPoint();
00160 throw;
00161
00162 }
00163
00164 }
00165 }
00166
00167 Bool_t TGo4Thread::Create ()
00168 {
00169 GO4TRACE((14,"TGo4Thread::Create()",__LINE__, __FILE__));
00170 if(!fbIsCreated)
00171
00172 {
00173 fxThread= new TThread(GetName(),
00174 (void(*) (void *)) &Threadfunc ,
00175 (void*) this);
00176 fxThread->Run();
00177 fbIsCreated=kTRUE;
00178 return kTRUE;
00179 }
00180 else
00181
00182 {
00183 return kFALSE;
00184 }
00185 }
00186
00187 Bool_t TGo4Thread::Cancel ()
00188 {
00189 GO4TRACE((14,"TGo4Thread::Cancel()",__LINE__, __FILE__));
00190
00191 if(fbIsCreated)
00192
00193 {
00194 TGo4Log::Debug(" Go4Thread ``%s'' -- Canceling TThread %d (PID:%d) ",
00195 GetName(), fiThreadSelfID, fiThreadPID);
00196
00197 if(fxThread)
00198 {
00199 GO4TRACE((13,"TGo4Thread::Cancel() -- canceling existing TThread",__LINE__, __FILE__));
00200 fbIsCreated=kFALSE;
00201 fbIsRunning=kTRUE;
00202 fxCondition->Signal();
00203 Sleep(500);
00204
00205
00206
00207
00208
00209
00210
00211 fxThread->Kill();
00212 delete fxThread;
00213
00214
00216
00217
00218
00219
00220
00221
00222
00223
00224 fxThread=0;
00225 fiThreadPID=0;
00226 fiThreadSelfID=0;
00227
00228 }
00229 else
00230 {
00231 GO4TRACE((13,"TGo4Thread::Cancel() -- Error: TThread pointer is zero!",__LINE__, __FILE__));
00232 TGo4Log::Debug(" Go4Thread ``%s'' Cancel -- Internal inconsistency error! ",GetName());
00233 throw TGo4RuntimeException();
00234 }
00235 return kTRUE;
00236 }
00237 else
00238
00239 {
00240 return kFALSE;
00241 }
00242 }
00243
00244 Bool_t TGo4Thread::ReCreate ()
00245 {
00246 GO4TRACE((14,"TGo4Thread::ReCreate()",__LINE__, __FILE__));
00247
00248 TThread* oldthread;
00249 if(fbIsCreated)
00250
00251
00252 {
00253 GO4TRACE((13,"TGo4Thread::ReCreate() -- old TThread existing",__LINE__, __FILE__));
00254 TGo4Log::Debug(" Recreating Go4Thread ``%s'' -- old TThread %d (PID:%d) ",
00255 GetName(), fiThreadSelfID, fiThreadPID);
00256
00257 if(fxThread)
00258 {
00259 GO4TRACE((13,"TGo4Thread::ReCreate() -- recreating existing TThread",__LINE__, __FILE__));
00260 Stop();
00261 oldthread=fxThread;
00262
00263 fxThread= new TThread(GetName(),
00264 (void(*) (void *)) &Threadfunc ,
00265 (void*) this);
00266
00267
00268 fbIsCreated=kFALSE;
00269 if(fbIsWaiting)
00270 {
00271 fxCondition->Signal();
00272
00273
00274 }
00275 TThread::Delete(oldthread);
00276
00277 fbIsCreated=kTRUE;
00278 fxThread->Run();
00279 Start();
00280
00281 }
00282 else
00283 {
00284 GO4TRACE((13,"TGo4Thread::ReCreate() -- Error: old TThread pointer is zero!",__LINE__, __FILE__));
00285 TGo4Log::Debug(" Go4Thread ``%s'' ReCreate -- Internal inconsistency error! ",GetName());
00286
00287 throw TGo4RuntimeException();
00288 }
00289 return kTRUE;
00290 }
00291 else
00292
00293 {
00294 GO4TRACE((13,"TGo4Thread::ReCreate() -- old TThread existing",__LINE__, __FILE__));
00295 Create();
00296 return kFALSE;
00297 }
00298 }
00299
00300 Bool_t TGo4Thread::Start ()
00301 {
00302 GO4TRACE((12,"TGo4Thread::Start()",__LINE__, __FILE__));
00303 if(!fbIsCreated)
00304
00305 {
00306
00307 GO4TRACE((11,"TGo4Thread::Start() -- creating new TThread",__LINE__, __FILE__));
00308 Create();
00309 }
00310 else
00311 {
00312
00313 GO4TRACE((11,"TGo4Thread::Start() -- TThread already existing",__LINE__, __FILE__));
00314 }
00315 Bool_t old=fbIsRunning;
00316 fbIsRunning=kTRUE;
00317 fxCondition->Signal();
00318 return old;
00319 }
00320
00321 Bool_t TGo4Thread::Stop ()
00322 {
00323 GO4TRACE((12,"TGo4Thread::Stop()",__LINE__, __FILE__));
00324 Bool_t old=fbIsRunning;
00325 fbIsRunning=kFALSE;
00326 return old;
00327 }
00328
00329 void TGo4Thread::Sleep (UInt_t millisecs)
00330 {
00331 GO4TRACE((12,"TGo4Thread::Sleep()",__LINE__, __FILE__));
00332 gSystem->Sleep(millisecs);
00333 TThread::CancelPoint();
00334 }
00335
00336 void TGo4Thread::SetSelfID()
00337 {
00338 fiThreadSelfID = TThread::SelfId();
00339 }
00340
00341 void TGo4Thread::SetPID()
00342 {
00343 fiThreadPID = gSystem->GetPid();
00344 }