Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

/Go4ThreadManager/TGo4Thread.cxx

Go to the documentation of this file.
00001 //---------------------------------------------------------------
00002 //        Go4 Release Package v2.10-5 (build 21005) 
00003 //                      03-Nov-2005
00004 //---------------------------------------------------------------
00005 //       The GSI Online Offline Object Oriented (Go4) Project
00006 //       Experiment Data Processing at DVEE 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 <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; // internal mode: go4thread responsible for runnable
00066       }
00067    else
00068       {
00069          TRACE((14,"TGo4Thread::~TGo4Thread() non internal mode",__LINE__, __FILE__));
00070          // do nothing
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          // copy is already source object
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; // we need reference to calling class instance
00100    TGo4Runnable* runnable = go4th->GetRunnable();
00101 
00102   // this is the function running as pthread...
00103   // initializations:
00104    go4th->SetPID();
00105    go4th->SetSelfID();
00106 //   fiThreadPID=gSystem->GetPid(); // set ids
00107 //   fiThreadSelfID=TThread::SelfId();
00108    TGo4Log::Debug(" TThread %d (PID:%d) of Go4Thread ``%s''  started... \n",
00109             go4th->GetSelfID(), go4th->GetPID(), go4th->GetName());
00110 
00111 for(;;) // loop keeps thread alive after exception has occured...
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(); //wait for funcrun condition
00126                    go4th->SetWaiting(kFALSE);
00127                    TGo4Log::Debug(" Go4Thread ``%s'' (PID:%d) running...\n",
00128                            go4th->GetName(), go4th->GetPID() );
00129                 }
00130             else
00131                {
00132                // Do Nothing, just continue
00133                }
00134 
00135             if(go4th->IsCreated())
00136                // normal  mode: enter runnable
00137                {
00138                TRACE((1,"TGo4Thread::Threadfunc(void*) entering running mode",__LINE__, __FILE__));
00139                   // call runnable prerun method before running:
00140                runnable->PreRun((void*) 0); // we are runnable's friend, can call protected method...
00141                while(go4th->IsRunning())
00142                   {
00143                      TThread::CancelPoint();
00144                      runnable->Run((void*) 0); // we are runnable's friend, can call protected method...
00145                   }
00146                    // call runnable postrun method before stopping
00147                runnable->PostRun((void*) 0); // we are runnable's friend, can call protected method...
00148 
00149                }
00150             else
00151                // aborting mode after condition release: loop cancel point
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         } // while(1)
00165     }// try
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       //runnable->UnexpectedCatch(); // do not handle alien exceptions!
00177       TThread::CancelPoint();
00178       throw; // otherwise, we have trouble with newer pthread
00179              // implementations that use one pid for all threads, e.g. Fedora2
00180     }
00181 
00182    } // for(;;) loop keeps thread alive
00183 }
00184 
00185 Bool_t TGo4Thread::Create ()
00186 {
00187    TRACE((14,"TGo4Thread::Create()",__LINE__, __FILE__));
00188    //if(!fxThread)
00189    if(!fbIsCreated)
00190      // thread not existing, create it
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      // thread instance already there...
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     // thread existing, then cancel
00212    {
00213       TGo4Log::Debug(" Go4Thread ``%s'' --  Canceling TThread %d (PID:%d) ",
00214                GetName(), fiThreadSelfID, fiThreadPID);
00215       //cout << "canceling thread "<<fiThreadSelfID<<endl;
00216       if(fxThread)
00217          {
00218          TRACE((13,"TGo4Thread::Cancel() -- canceling existing TThread",__LINE__, __FILE__));
00219          fbIsCreated=kFALSE;
00220          fbIsRunning=kTRUE; // these settings let Threadfunc enter Cancel loop
00221          fxCondition->Signal();  // unlock condition mutex before deleting it
00222          Sleep(500); // waitstate for Threadfunc to enter cancel loop after condition
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     // no such thread...
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     // thread existing, then recreate possible
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        //cout << "recreating thread "<<GetName()<<endl;
00259       if(fxThread)
00260          {
00261             TRACE((13,"TGo4Thread::ReCreate() -- recreating existing TThread",__LINE__, __FILE__));
00262             Stop();// halt runnable
00263             oldthread=fxThread; // remember old TThread
00264             // first start new TThread of same Threadfunc and runnable:
00265             fxThread= new TThread(GetName(),
00266                                (void(*) (void *)) &Threadfunc ,
00267                                (void*) this);
00268 
00269             // then kill the old TThread, so Threadfunc may ReCreate() itself
00270             fbIsCreated=kFALSE;
00271             if(fbIsWaiting)
00272             {
00273                fxCondition->Signal();  // unlock condition mutex before deleting it
00274                                        // this will not start the runnable, fbIsRunning still false
00275                //fbIsWaiting=kFALSE;    // keep flag consistent with Threadfunc state..
00276             }
00277             TThread::Delete(oldthread);
00278             delete oldthread;
00279             fbIsCreated=kTRUE;
00280             fxThread->Run(); // does this work if thread recreates itself?
00281             Start(); // start runnable in new TThread
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             //cout << "TGo4Thread "<<GetName()<<" ReCreate inconsistency error!"<<endl;
00289             throw TGo4RuntimeException();
00290          }
00291       return kTRUE;
00292     }
00293   else //if(fbIsCreated)
00294     // no old thread, then create new one
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       // check if thread is up
00307       {
00308          // not yet created, then do so
00309          TRACE((11,"TGo4Thread::Start() -- creating new TThread",__LINE__, __FILE__));
00310          Create();
00311       }
00312    else
00313       {
00314          // do nothing, thread already there
00315          TRACE((11,"TGo4Thread::Start() -- TThread already existing",__LINE__, __FILE__));
00316       }
00317    Bool_t old=fbIsRunning;
00318    fbIsRunning=kTRUE;
00319    fxCondition->Signal(); // wake up waiting threadfunction
00320    return old; // old status of workfunc requested by thread list
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; // old status of workfunc requested by thread list
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 //----------------------------END OF GO4 SOURCE FILE ---------------------

Generated on Tue Nov 8 10:56:07 2005 for Go4-v2.10-5 by doxygen1.2.15