Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

TGo4Thread.cxx

Go to the documentation of this file.
00001 //-------------------------------------------------------------
00002 //        Go4 Release Package v3.04-01 (build 30401)
00003 //                      28-November-2008
00004 //---------------------------------------------------------------
00005 //   The GSI Online Offline Object Oriented (Go4) Project
00006 //   Experiment Data Processing at EE department, GSI
00007 //---------------------------------------------------------------
00008 //
00009 //Copyright (C) 2000- Gesellschaft f. Schwerionenforschung, GSI
00010 //                    Planckstr. 1, 64291 Darmstadt, Germany
00011 //Contact:            http://go4.gsi.de
00012 //----------------------------------------------------------------
00013 //This software can be used under the license agreements as stated
00014 //in Go4License.txt file which is part of the distribution.
00015 //----------------------------------------------------------------
00016 #include "TGo4Thread.h"
00017 
00018 #include "Riostream.h"
00019 
00020 #include "TThread.h"
00021 #include "TSystem.h"
00022 #include "TCondition.h"
00023 
00024 #include "TGo4Runnable.h"
00025 #include "TGo4Log.h"
00026 #include "TGo4LockGuard.h"
00027 #include "Go4Exceptions.h"
00028 
00029 TGo4Thread::TGo4Thread(const TGo4Thread &right)
00030    :TNamed(right)
00031 {
00032    TRACE((14,"TGo4Thread::TGo4Thread() copy constructor",__LINE__, __FILE__));
00033    fxRunnable = right.fxRunnable;
00034    fbIsInternal = right.fbIsInternal;
00035    fxCondition = new TCondition();
00036 }
00037 
00038 TGo4Thread::TGo4Thread (const char* name, TGo4Runnable* runnable, Bool_t internal)
00039    :TNamed(name,"This is a TGo4Thread"),
00040    fbIsCreated(kFALSE),
00041    fbIsRunning(kFALSE),
00042    fiThreadPID(0),
00043    fiThreadSelfID(0),
00044    fbIsWaiting(kFALSE),
00045    fxThread(0)
00046 {
00047    TRACE((14,"TGo4Thread::TGo4Thread(Text_t*, TGo4Runnable*, Bool_t) constructor",__LINE__, __FILE__));
00048 
00049    TGo4Log::Debug(" New Go4Thread ``%s'' created ",name);
00050    fxRunnable = runnable;
00051    fbIsInternal = internal;
00052    fxCondition = new TCondition();
00053    fxRunnable->SetThread(this);
00054 }
00055 
00056 
00057 TGo4Thread::~TGo4Thread()
00058 {
00059    TRACE((14,"TGo4Thread::~TGo4Thread() destructor",__LINE__, __FILE__));
00060 
00061    Stop();
00062    Cancel();
00063    delete fxCondition;
00064    if(fbIsInternal)
00065       {
00066          TRACE((14,"TGo4Thread::~TGo4Thread() internal mode",__LINE__, __FILE__));
00067          TGo4Log::Debug(" Go4Thread ``%s'' deleting runnable ``%s'' ",
00068                   GetName(),fxRunnable->GetName());
00069          delete fxRunnable; // internal mode: go4thread responsible for runnable
00070       }
00071    else
00072       {
00073          TRACE((14,"TGo4Thread::~TGo4Thread() non internal mode",__LINE__, __FILE__));
00074          // do nothing
00075       }
00076 
00077 }
00078 
00079 void TGo4Thread::Threadfunc (void* arg)
00080 {
00081    TRACE((2,"TGo4Thread::Threadfunc(void*)",__LINE__, __FILE__));
00082    TGo4Thread* go4th= (TGo4Thread*) arg; // we need reference to calling class instance
00083    TGo4Runnable* runnable = go4th->GetRunnable();
00084 
00085   // this is the function running as pthread...
00086   // initializations:
00087    go4th->SetPID();
00088    go4th->SetSelfID();
00089 //   fiThreadPID=gSystem->GetPid(); // set ids
00090 //   fiThreadSelfID=TThread::SelfId();
00091    TGo4Log::Debug(" TThread %d (PID:%d) of Go4Thread ``%s''  started... \n",
00092             go4th->GetSelfID(), go4th->GetPID(), go4th->GetName());
00093 
00094 for(;;) // loop keeps thread alive after exception has occured...
00095    {
00096    try
00097       {
00098       TRACE((1,"TGo4Thread::Threadfunc(void*) try block",__LINE__, __FILE__));
00099       while(1)
00100          {
00101             TThread::CancelPoint();
00102             if( !(go4th->IsRunning()) )
00103                {
00104                   TRACE((1,"TGo4Thread::Threadfunc(void*) waiting mode",__LINE__, __FILE__));
00105                   TGo4Log::Debug(" Go4Thread ``%s'' (PID:%d) waiting...\n",
00106                            go4th->GetName(), go4th->GetPID());
00107                    go4th->SetWaiting(kTRUE);
00108                    go4th->GetCondition()->Wait(); //wait for funcrun condition
00109                    go4th->SetWaiting(kFALSE);
00110                    TGo4Log::Debug(" Go4Thread ``%s'' (PID:%d) running...\n",
00111                            go4th->GetName(), go4th->GetPID() );
00112                 }
00113             else
00114                {
00115                // Do Nothing, just continue
00116                }
00117 
00118             if(go4th->IsCreated())
00119                // normal  mode: enter runnable
00120                {
00121                TRACE((1,"TGo4Thread::Threadfunc(void*) entering running mode",__LINE__, __FILE__));
00122                   // call runnable prerun method before running:
00123                runnable->PreRun((void*) 0); // we are runnable's friend, can call protected method...
00124                while(go4th->IsRunning())
00125                   {
00126                      TThread::CancelPoint();
00127                      runnable->Run((void*) 0); // we are runnable's friend, can call protected method...
00128                   }
00129                    // call runnable postrun method before stopping
00130                runnable->PostRun((void*) 0); // we are runnable's friend, can call protected method...
00131 
00132                }
00133             else
00134                // aborting mode after condition release: loop cancel point
00135                {
00136                   TRACE((1,"TGo4Thread::Threadfunc(void*) entering Cancel loop",__LINE__, __FILE__));
00137                   TGo4Log::Debug(" Go4Thread ``%s''  entering Cancel loop\n ", go4th->GetName());
00138                   while(!(go4th->IsCreated()))
00139                      {
00140                         {
00141                         #ifdef WIN32
00142                            return; // cancel point does not work on windows; escape to root thread framework...
00143                         #endif
00144                         TRACE((1,"TGo4Thread::Threadfunc(void*) in Cancel loop",__LINE__, __FILE__));
00145                         Sleep(500);
00146                         TThread::CancelPoint();
00147                         }
00148                      }
00149                }
00150         } // while(1)
00151     }// try
00152   catch(TGo4Exception& ex)
00153     {
00154       TRACE((1,"TGo4Thread::Threadfunc(void*) Go4Exception Catch",__LINE__, __FILE__));
00155       runnable->ThreadCatch(ex);
00156       TThread::CancelPoint();
00157     }
00158 
00159   catch(...)
00160     {
00161       TRACE((1,"TGo4Thread::Threadfunc(void*) Unexpected Catch",__LINE__, __FILE__));
00162       //runnable->UnexpectedCatch(); // do not handle alien exceptions!
00163       TThread::CancelPoint();
00164       throw; // otherwise, we have trouble with newer pthread
00165              // implementations that use one pid for all threads, e.g. Fedora2
00166     }
00167 
00168    } // for(;;) loop keeps thread alive
00169 }
00170 
00171 Bool_t TGo4Thread::Create ()
00172 {
00173    TRACE((14,"TGo4Thread::Create()",__LINE__, __FILE__));
00174    if(!fbIsCreated)
00175      // thread not existing, create it
00176      {
00177        fxThread= new TThread(GetName(),
00178                             (void(*) (void *)) &Threadfunc ,
00179                             (void*) this);
00180        fxThread->Run();
00181        fbIsCreated=kTRUE;
00182        return kTRUE;
00183      }
00184    else
00185      // thread instance already there...
00186      {
00187        return kFALSE;
00188      }
00189 }
00190 
00191 Bool_t TGo4Thread::Cancel ()
00192 {
00193     TRACE((14,"TGo4Thread::Cancel()",__LINE__, __FILE__));
00194 
00195     if(fbIsCreated)
00196     // thread existing, then cancel
00197    {
00198       TGo4Log::Debug(" Go4Thread ``%s'' --  Canceling TThread %d (PID:%d) ",
00199                GetName(), fiThreadSelfID, fiThreadPID);
00200       //cout << "canceling thread "<<fiThreadSelfID<<endl;
00201       if(fxThread)
00202          {
00203          TRACE((13,"TGo4Thread::Cancel() -- canceling existing TThread",__LINE__, __FILE__));
00204          fbIsCreated=kFALSE;
00205          fbIsRunning=kTRUE; // these settings let Threadfunc enter Cancel loop
00206          fxCondition->Signal();  // unlock condition mutex before deleting it
00207          Sleep(500); // waitstate for Threadfunc to enter cancel loop after condition
00208 
00209 
00210 
00211 // this does not work properly for ROOT versions < 5.17-04
00212 // due to bug in static Delete() method (see root bug report 31085)
00213 //         TThread::Delete(fxThread);
00214 // use workaround, later with root version ifdefs:
00215         fxThread->Kill();
00216         delete fxThread;
00217 // note: this will skip the thread Cleanup(), but we do not use this feature in Go4
00218 
00220 //#ifndef WIN32
00221 //            // the following cleanup might fail on win32, better not do it...
00222 //         if(TThread::GetThread(fiThreadSelfID)!=0)
00223 //            {
00224 //               //cout <<"thread of "<<fiThreadSelfID<<" not yet deleted, do it now:" << endl;
00225 //               delete fxThread; // only delete thread if Cleanup method of TThread::Delete not yet invoked
00226 //            }
00227 //#endif
00228          fxThread=0;
00229          fiThreadPID=0;
00230          fiThreadSelfID=0;
00231 
00232          }
00233       else
00234          {
00235             TRACE((13,"TGo4Thread::Cancel() -- Error: TThread pointer is zero!",__LINE__, __FILE__));
00236             TGo4Log::Debug(" Go4Thread ``%s'' Cancel -- Internal inconsistency error! ",GetName());
00237             throw TGo4RuntimeException();
00238          }
00239       return kTRUE;
00240     }
00241   else
00242     // no such thread...
00243     {
00244       return kFALSE;
00245     }
00246 }
00247 
00248 Bool_t TGo4Thread::ReCreate ()
00249 {
00250    TRACE((14,"TGo4Thread::ReCreate()",__LINE__, __FILE__));
00251 
00252    TThread* oldthread;
00253    if(fbIsCreated)
00254     // thread existing, then recreate possible
00255 
00256     {
00257     TRACE((13,"TGo4Thread::ReCreate() -- old TThread existing",__LINE__, __FILE__));
00258     TGo4Log::Debug(" Recreating Go4Thread ``%s'' --  old TThread %d (PID:%d) ",
00259                GetName(), fiThreadSelfID, fiThreadPID);
00260        //cout << "recreating thread "<<GetName()<<endl;
00261       if(fxThread)
00262          {
00263             TRACE((13,"TGo4Thread::ReCreate() -- recreating existing TThread",__LINE__, __FILE__));
00264             Stop();// halt runnable
00265             oldthread=fxThread; // remember old TThread
00266             // first start new TThread of same Threadfunc and runnable:
00267             fxThread= new TThread(GetName(),
00268                                (void(*) (void *)) &Threadfunc ,
00269                                (void*) this);
00270 
00271             // then kill the old TThread, so Threadfunc may ReCreate() itself
00272             fbIsCreated=kFALSE;
00273             if(fbIsWaiting)
00274             {
00275                fxCondition->Signal();  // unlock condition mutex before deleting it
00276                                        // this will not start the runnable, fbIsRunning still false
00277                //fbIsWaiting=kFALSE;    // keep flag consistent with Threadfunc state..
00278             }
00279             TThread::Delete(oldthread);
00280             //delete oldthread;
00281             fbIsCreated=kTRUE;
00282             fxThread->Run(); // does this work if thread recreates itself?
00283             Start(); // start runnable in new TThread
00284 
00285          }
00286       else
00287          {
00288             TRACE((13,"TGo4Thread::ReCreate() -- Error: old TThread pointer is zero!",__LINE__, __FILE__));
00289             TGo4Log::Debug(" Go4Thread ``%s'' ReCreate -- Internal inconsistency error! ",GetName());
00290             //cout << "TGo4Thread "<<GetName()<<" ReCreate inconsistency error!"<<endl;
00291             throw TGo4RuntimeException();
00292          }
00293       return kTRUE;
00294     }
00295   else //if(fbIsCreated)
00296     // no old thread, then create new one
00297     {
00298       TRACE((13,"TGo4Thread::ReCreate() -- old TThread existing",__LINE__, __FILE__));
00299       Create();
00300       return kFALSE;
00301     }
00302 }
00303 
00304 Bool_t TGo4Thread::Start ()
00305 {
00306    TRACE((12,"TGo4Thread::Start()",__LINE__, __FILE__));
00307    if(!fbIsCreated)
00308       // check if thread is up
00309       {
00310          // not yet created, then do so
00311          TRACE((11,"TGo4Thread::Start() -- creating new TThread",__LINE__, __FILE__));
00312          Create();
00313       }
00314    else
00315       {
00316          // do nothing, thread already there
00317          TRACE((11,"TGo4Thread::Start() -- TThread already existing",__LINE__, __FILE__));
00318       }
00319    Bool_t old=fbIsRunning;
00320    fbIsRunning=kTRUE;
00321    fxCondition->Signal(); // wake up waiting threadfunction
00322    return old; // old status of workfunc requested by thread list
00323 }
00324 
00325 Bool_t TGo4Thread::Stop ()
00326 {
00327    TRACE((12,"TGo4Thread::Stop()",__LINE__, __FILE__));
00328    Bool_t old=fbIsRunning;
00329    fbIsRunning=kFALSE;
00330    return old; // old status of workfunc requested by thread list
00331 }
00332 
00333 void TGo4Thread::Sleep (UInt_t millisecs)
00334 {
00335    TRACE((12,"TGo4Thread::Sleep()",__LINE__, __FILE__));
00336    gSystem->Sleep(millisecs);
00337    TThread::CancelPoint();
00338 }
00339 
00340 void TGo4Thread::SetSelfID()
00341 {
00342    fiThreadSelfID = TThread::SelfId();
00343 }
00344 
00345 void TGo4Thread::SetPID()
00346 {
00347    fiThreadPID = gSystem->GetPid();
00348 }
00349 
00350 //----------------------------END OF GO4 SOURCE FILE ---------------------

Generated on Fri Nov 28 12:59:31 2008 for Go4-v3.04-1 by  doxygen 1.4.2