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