TThread.cxx

Go to the documentation of this file.
00001 // @(#)root/thread:$Id: TThread.cxx 35527 2010-09-21 12:27:01Z brun $
00002 // Author: Fons Rademakers   02/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 // TThread                                                              //
00015 //                                                                      //
00016 // This class implements threads. A thread is an execution environment  //
00017 // much lighter than a process. A single process can have multiple      //
00018 // threads. The actual work is done via the TThreadImp class (either    //
00019 // TPosixThread or TWin32Thread).                                       //
00020 //                                                                      //
00021 //////////////////////////////////////////////////////////////////////////
00022 
00023 #include "RConfigure.h"
00024 
00025 #include "TThread.h"
00026 #include "TThreadImp.h"
00027 #include "TThreadFactory.h"
00028 #include "TROOT.h"
00029 #include "TApplication.h"
00030 #include "TVirtualPad.h"
00031 #include "TMethodCall.h"
00032 #include "TTimeStamp.h"
00033 #include "TInterpreter.h"
00034 #include "TError.h"
00035 #include "Varargs.h"
00036 
00037 TThreadImp     *TThread::fgThreadImp = 0;
00038 Long_t          TThread::fgMainId = 0;
00039 TThread        *TThread::fgMain = 0;
00040 TMutex         *TThread::fgMainMutex;
00041 char  *volatile TThread::fgXAct = 0;
00042 TMutex         *TThread::fgXActMutex = 0;
00043 TCondition     *TThread::fgXActCondi = 0;
00044 void **volatile TThread::fgXArr = 0;
00045 volatile Int_t  TThread::fgXAnb = 0;
00046 volatile Int_t  TThread::fgXArt = 0;
00047 
00048 static void CINT_alloc_lock()   { gGlobalMutex->Lock(); }
00049 static void CINT_alloc_unlock() { gGlobalMutex->UnLock(); }
00050 
00051 //------------------------------------------------------------------------------
00052 
00053 // Set gGlobalMutex to 0 when Thread library gets unloaded
00054 class TGlobalMutexGuard {
00055 public:
00056    TGlobalMutexGuard() { }
00057    ~TGlobalMutexGuard() { gGlobalMutex = 0; }
00058 };
00059 static TGlobalMutexGuard gGlobalMutexGuardInit;
00060 
00061 //------------------------------------------------------------------------------
00062 
00063 class TJoinHelper {
00064 private:
00065    TThread    *fT;
00066    TThread    *fH;
00067    void      **fRet;
00068    Long_t      fRc;
00069    TMutex     *fM;
00070    TCondition *fC;
00071 
00072    static void JoinFunc(void *p);
00073 
00074 public:
00075    TJoinHelper(TThread *th, void **ret);
00076    ~TJoinHelper();
00077 
00078    Int_t Join();
00079 };
00080 
00081 //______________________________________________________________________________
00082 TJoinHelper::TJoinHelper(TThread *th, void **ret)
00083    : fT(th), fRet(ret), fRc(0), fM(new TMutex), fC(new TCondition(fM))
00084 {
00085    // Constructor of Thread helper class.
00086 
00087    fH = new TThread("JoinHelper", JoinFunc, this);
00088 }
00089 
00090 //______________________________________________________________________________
00091 TJoinHelper::~TJoinHelper()
00092 {
00093    // Destructor.
00094 
00095    delete fC;
00096    delete fM;
00097    delete fH;
00098 }
00099 
00100 //______________________________________________________________________________
00101 void TJoinHelper::JoinFunc(void *p)
00102 {
00103    // Static method which runs in a separate thread to handle thread
00104    // joins without blocking the main thread.
00105 
00106    TJoinHelper *jp = (TJoinHelper*)p;
00107 
00108    jp->fRc = jp->fT->Join(jp->fRet);
00109 
00110    jp->fM->Lock();
00111    jp->fC->Signal();
00112    jp->fM->UnLock();
00113 
00114    TThread::Exit(0);
00115 }
00116 
00117 //______________________________________________________________________________
00118 Int_t TJoinHelper::Join()
00119 {
00120    // Thread join function.
00121 
00122    fM->Lock();
00123    fH->Run();
00124 
00125    while (kTRUE) {
00126       int r = fC->TimedWaitRelative(100);  // 100 ms
00127 
00128       if (r == 0) break;
00129 
00130       gSystem->ProcessEvents();
00131    }
00132 
00133    fM->UnLock();
00134 
00135    return fRc;
00136 }
00137 
00138 
00139 //------------------------------------------------------------------------------
00140 
00141 ClassImp(TThread)
00142 
00143 
00144 //______________________________________________________________________________
00145 TThread::TThread(VoidRtnFunc_t fn, void *arg, EPriority pri)
00146    : TNamed("<anon>", "")
00147 {
00148    // Create a thread. Specify the function or static class method
00149    // to be executed by the thread and a pointer to the argument structure.
00150    // The user function should return a void*. To start the thread call Run().
00151 
00152    fDetached  = kFALSE;
00153    fFcnVoid   = 0;
00154    fFcnRetn   = fn;
00155    fPriority  = pri;
00156    fThreadArg = arg;
00157    Constructor();
00158    fNamed     = kFALSE;
00159 }
00160 
00161 //______________________________________________________________________________
00162 TThread::TThread(VoidFunc_t fn, void *arg, EPriority pri)
00163    : TNamed("<anon>", "")
00164 {
00165    // Create a detached thread. Specify the function or static class method
00166    // to be executed by the thread and a pointer to the argument structure.
00167    // To start the thread call Run().
00168 
00169    fDetached  = kTRUE;
00170    fFcnRetn   = 0;
00171    fFcnVoid   = fn;
00172    fPriority  = pri;
00173    fThreadArg = arg;
00174    Constructor();
00175    fNamed     = kFALSE;
00176 }
00177 
00178 //______________________________________________________________________________
00179 TThread::TThread(const char *thname, VoidRtnFunc_t fn, void *arg,
00180                  EPriority pri) : TNamed(thname, "")
00181 {
00182    // Create thread with a name. Specify the function or static class method
00183    // to be executed by the thread and a pointer to the argument structure.
00184    // The user function should return a void*. To start the thread call Run().
00185 
00186    fDetached  = kFALSE;
00187    fFcnVoid   = 0;
00188    fFcnRetn   = fn;
00189    fPriority  = pri;
00190    fThreadArg = arg;
00191    Constructor();
00192    fNamed     = kTRUE;
00193 }
00194 
00195 //______________________________________________________________________________
00196 TThread::TThread(const char *thname, VoidFunc_t fn, void *arg,
00197                  EPriority pri) : TNamed(thname, "")
00198 {
00199    // Create a detached thread with a name. Specify the function or static
00200    // class method to be executed by the thread and a pointer to the argument
00201    // structure. To start the thread call Run().
00202 
00203    fDetached  = kTRUE;
00204    fFcnRetn   = 0;
00205    fFcnVoid   = fn;
00206    fPriority  = pri;
00207    fThreadArg = arg;
00208    Constructor();
00209    fNamed     = kTRUE;
00210 }
00211 
00212 //______________________________________________________________________________
00213 TThread::TThread(Long_t id)
00214 {
00215    // Create a TThread for a already running thread.
00216 
00217    fDetached  = kTRUE;
00218    fFcnRetn   = 0;
00219    fFcnVoid   = 0;
00220    fPriority  = kNormalPriority;
00221    fThreadArg = 0;
00222    Constructor();
00223    fNamed     = kFALSE;
00224    fId = (id ? id : SelfId());
00225    fState = kRunningState;
00226 
00227    if (gDebug)
00228       Info("TThread::TThread", "TThread attached to running thread");
00229 }
00230 
00231 //______________________________________________________________________________
00232 Bool_t TThread::IsInitialized()
00233 {
00234    // Return true, if the TThread objects have been initialize.   If false,
00235    // the process is (from ROOT's point of view) single threaded.
00236 
00237    if (fgThreadImp) return kTRUE;
00238    else return kFALSE;
00239 }
00240 
00241 //______________________________________________________________________________
00242 void TThread::Init()
00243 {
00244    // Initialize global state and variables once.
00245 
00246    if (fgThreadImp) return;
00247 
00248    fgThreadImp = gThreadFactory->CreateThreadImp();
00249    fgMainId    = fgThreadImp->SelfId();
00250    fgMainMutex = new TMutex(kTRUE);
00251    gThreadTsd  = TThread::Tsd;
00252    gThreadXAR  = TThread::XARequest;
00253 
00254    // Create the single global mutex
00255    gGlobalMutex = new TMutex(kTRUE);
00256    gCint->SetAlloclockfunc(CINT_alloc_lock);
00257    gCint->SetAllocunlockfunc(CINT_alloc_unlock);
00258 }
00259 
00260 //______________________________________________________________________________
00261 void TThread::Constructor()
00262 {
00263    // Common thread constructor.
00264 
00265    fHolder = 0;
00266    fClean  = 0;
00267    fState  = kNewState;
00268 
00269    fId = -1;
00270    fHandle= 0;
00271    if (!fgThreadImp) Init();
00272 
00273    SetComment("Constructor: MainMutex Locking");
00274    Lock();
00275    SetComment("Constructor: MainMutex Locked");
00276    fTsd[0] = gPad;
00277    fTsd[1] = 0;    // For TClass
00278 
00279    if (fgMain) fgMain->fPrev = this;
00280    fNext = fgMain; fPrev = 0; fgMain = this;
00281 
00282    UnLock();
00283    SetComment();
00284 
00285    // thread is set up in initialisation routine or Run().
00286 }
00287 
00288 //______________________________________________________________________________
00289 TThread::~TThread()
00290 {
00291    // Cleanup the thread.
00292 
00293    if (gDebug)
00294       Info("TThread::~TThread", "thread deleted");
00295 
00296    // Disconnect thread instance
00297 
00298    SetComment("Destructor: MainMutex Locking");
00299    Lock();
00300    SetComment("Destructor: MainMutex Locked");
00301 
00302    if (fPrev) fPrev->fNext = fNext;
00303    if (fNext) fNext->fPrev = fPrev;
00304    if (fgMain == this) fgMain = fNext;
00305 
00306    UnLock();
00307    SetComment();
00308    if (fHolder) *fHolder = 0;
00309 }
00310 
00311 //______________________________________________________________________________
00312 Int_t TThread::Delete(TThread *&th)
00313 {
00314    // Static method to delete the specified thread.
00315 
00316    if (!th) return 0;
00317    th->fHolder = &th;
00318 
00319    if (th->fState == kRunningState) {     // Cancel if running
00320       th->fState = kDeletingState;
00321 
00322       if (gDebug)
00323          th->Info("TThread::Delete", "deleting thread");
00324 
00325       th->Kill();
00326       return -1;
00327    }
00328 
00329    CleanUp();
00330    return 0;
00331 }
00332 
00333 //______________________________________________________________________________
00334 Int_t TThread::Exists()
00335 {
00336    // Static method to check if threads exist.
00337    // Returns the number of running threads.
00338 
00339    Lock();
00340 
00341    Int_t num = 0;
00342    for (TThread *l = fgMain; l; l = l->fNext)
00343       num++; //count threads
00344 
00345    UnLock();
00346 
00347    return num;
00348 }
00349 
00350 //______________________________________________________________________________
00351 void TThread::SetPriority(EPriority pri)
00352 {
00353    // Set thread priority.
00354 
00355    fPriority = pri;
00356 }
00357 
00358 //______________________________________________________________________________
00359 TThread *TThread::GetThread(Long_t id)
00360 {
00361    // Static method to find a thread by id.
00362 
00363    TThread *myTh;
00364 
00365    Lock();
00366 
00367    for (myTh = fgMain; myTh && (myTh->fId != id); myTh = myTh->fNext) { }
00368 
00369    UnLock();
00370 
00371    return myTh;
00372 }
00373 
00374 //______________________________________________________________________________
00375 TThread *TThread::GetThread(const char *name)
00376 {
00377    // Static method to find a thread by name.
00378 
00379    TThread *myTh;
00380 
00381    Lock();
00382 
00383    for (myTh = fgMain; myTh && (strcmp(name, myTh->GetName())); myTh = myTh->fNext) { }
00384 
00385    UnLock();
00386 
00387    return myTh;
00388 }
00389 
00390 //______________________________________________________________________________
00391 TThread *TThread::Self()
00392 {
00393    // Static method returning pointer to current thread.
00394 
00395    return GetThread(SelfId());
00396 }
00397 
00398 
00399 //______________________________________________________________________________
00400 Long_t TThread::Join(void **ret)
00401 {
00402    // Join this thread.
00403 
00404    if (fId == -1) {
00405       Error("Join", "thread not running");
00406       return -1;
00407    }
00408 
00409    if (fDetached) {
00410       Error("Join", "cannot join detached thread");
00411       return -1;
00412    }
00413 
00414    if (SelfId() != fgMainId)
00415       return fgThreadImp->Join(this, ret);
00416 
00417    // do not block the main thread, use helper thread
00418    TJoinHelper helper(this, ret);
00419 
00420    return helper.Join();
00421 }
00422 
00423 //______________________________________________________________________________
00424 Long_t TThread::Join(Long_t jid, void **ret)
00425 {
00426    // Static method to join a thread by id.
00427 
00428    TThread *myTh = GetThread(jid);
00429 
00430    if (!myTh) {
00431       ::Error("TThread::Join", "cannot find thread 0x%lx", jid);
00432       return -1L;
00433    }
00434 
00435    return myTh->Join(ret);
00436 }
00437 
00438 //______________________________________________________________________________
00439 Long_t TThread::SelfId()
00440 {
00441    // Static method returning the id for the current thread.
00442 
00443    if (!fgThreadImp) Init();
00444 
00445    return fgThreadImp->SelfId();
00446 }
00447 
00448 //______________________________________________________________________________
00449 Int_t TThread::Run(void *arg)
00450 {
00451    // Start the thread. This starts the static method TThread::Function()
00452    // which calls the user function specified in the TThread ctor with
00453    // the arg argument.
00454 
00455    if (arg) fThreadArg = arg;
00456 
00457    SetComment("Run: MainMutex locking");
00458    Lock();
00459    SetComment("Run: MainMutex locked");
00460 
00461    int iret = fgThreadImp->Run(this);
00462 
00463    fState = iret ? kInvalidState : kRunningState;
00464 
00465    if (gDebug)
00466       Info("TThread::Run", "thread run requested");
00467 
00468    UnLock();
00469    SetComment();
00470    return iret;
00471 }
00472 
00473 //______________________________________________________________________________
00474 Int_t TThread::Kill()
00475 {
00476    // Kill this thread.
00477 
00478    if (fState != kRunningState && fState != kDeletingState) {
00479       if (gDebug)
00480          Warning("TThread::Kill", "thread is not running");
00481       return 13;
00482    } else {
00483       if (fState == kRunningState ) fState = kCancelingState;
00484       return fgThreadImp->Kill(this);
00485    }
00486 }
00487 
00488 //______________________________________________________________________________
00489 Int_t TThread::Kill(Long_t id)
00490 {
00491    // Static method to kill the thread by id.
00492 
00493    TThread *th = GetThread(id);
00494    if (th) {
00495       return fgThreadImp->Kill(th);
00496    } else  {
00497       if (gDebug)
00498          ::Warning("TThread::Kill(Long_t)", "thread 0x%lx not found", id);
00499       return 13;
00500    }
00501 }
00502 
00503 //______________________________________________________________________________
00504 Int_t TThread::Kill(const char *name)
00505 {
00506    // Static method to kill thread by name.
00507 
00508    TThread *th = GetThread(name);
00509    if (th) {
00510       return fgThreadImp->Kill(th);
00511    } else  {
00512       if (gDebug)
00513          ::Warning("TThread::Kill(const char*)", "thread %s not found", name);
00514       return 13;
00515    }
00516 }
00517 
00518 //______________________________________________________________________________
00519 Int_t TThread::SetCancelOff()
00520 {
00521    // Static method to turn off thread cancellation.
00522 
00523    return fgThreadImp->SetCancelOff();
00524 }
00525 
00526 //______________________________________________________________________________
00527 Int_t TThread::SetCancelOn()
00528 {
00529    // Static method to turn on thread cancellation.
00530 
00531    return fgThreadImp->SetCancelOn();
00532 }
00533 
00534 //______________________________________________________________________________
00535 Int_t TThread::SetCancelAsynchronous()
00536 {
00537    // Static method to set asynchronous cancellation.
00538 
00539    return fgThreadImp->SetCancelAsynchronous();
00540 }
00541 
00542 //______________________________________________________________________________
00543 Int_t TThread::SetCancelDeferred()
00544 {
00545    // Static method to set deffered cancellation.
00546 
00547    return fgThreadImp->SetCancelDeferred();
00548 }
00549 
00550 //______________________________________________________________________________
00551 Int_t TThread::CancelPoint()
00552 {
00553    // Static method to set a cancellation point.
00554 
00555    return fgThreadImp->CancelPoint();
00556 }
00557 
00558 //______________________________________________________________________________
00559 Int_t TThread::CleanUpPush(void *free, void *arg)
00560 {
00561    // Static method which pushes thread cleanup method on stack.
00562    // Returns 0 in case of success and -1 in case of error.
00563 
00564    TThread *th = Self();
00565    if (th)
00566       return fgThreadImp->CleanUpPush(&(th->fClean), free, arg);
00567    return -1;
00568 }
00569 
00570 //______________________________________________________________________________
00571 Int_t TThread::CleanUpPop(Int_t exe)
00572 {
00573    // Static method which pops thread cleanup method off stack.
00574    // Returns 0 in case of success and -1 in case of error.
00575 
00576    TThread *th = Self();
00577    if (th)
00578       return fgThreadImp->CleanUpPop(&(th->fClean), exe);
00579    return -1;
00580 }
00581 
00582 //______________________________________________________________________________
00583 Int_t TThread::CleanUp()
00584 {
00585    // Static method to cleanup the calling thread.
00586 
00587    TThread *th = Self();
00588    if (!th) return 13;
00589 
00590    fgThreadImp->CleanUp(&(th->fClean));
00591    fgMainMutex->CleanUp();
00592    if (fgXActMutex)
00593       fgXActMutex->CleanUp();
00594 
00595    if (th->fHolder)
00596       delete th;
00597 
00598    return 0;
00599 }
00600 
00601 //______________________________________________________________________________
00602 void TThread::AfterCancel(TThread *th)
00603 {
00604    // Static method which is called after the thread has been canceled.
00605 
00606    if (th) {
00607       th->fState = kCanceledState;
00608       if (gDebug)
00609          th->Info("TThread::AfterCancel", "thread is canceled");
00610    } else
00611       ::Error("TThread::AfterCancel", "zero thread pointer passed");
00612 }
00613 
00614 //______________________________________________________________________________
00615 Int_t TThread::Exit(void *ret)
00616 {
00617    // Static method which terminates the execution of the calling thread.
00618 
00619    return fgThreadImp->Exit(ret);
00620 }
00621 
00622 //______________________________________________________________________________
00623 Int_t TThread::Sleep(ULong_t secs, ULong_t nanos)
00624 {
00625    // Static method to sleep the calling thread.
00626 
00627    UInt_t ms = UInt_t(secs * 1000) + UInt_t(nanos / 1000000);
00628    if (gSystem) gSystem->Sleep(ms);
00629    return 0;
00630 }
00631 
00632 //______________________________________________________________________________
00633 Int_t TThread::GetTime(ULong_t *absSec, ULong_t *absNanoSec)
00634 {
00635    // Static method to get the current time. Returns
00636    // the number of seconds.
00637 
00638    TTimeStamp t;
00639    if (absSec)     *absSec     = t.GetSec();
00640    if (absNanoSec) *absNanoSec = t.GetNanoSec();
00641    return t.GetSec();
00642 }
00643 
00644 //______________________________________________________________________________
00645 Int_t TThread::Lock()
00646 {
00647    // Static method to lock the main thread mutex.
00648 
00649    return (fgMainMutex ? fgMainMutex->Lock() : 0);
00650 }
00651 
00652 //______________________________________________________________________________
00653 Int_t TThread::TryLock()
00654 {
00655    // Static method to try to lock the main thread mutex.
00656 
00657    return (fgMainMutex ? fgMainMutex->TryLock() : 0);
00658 }
00659 
00660 //______________________________________________________________________________
00661 Int_t TThread::UnLock()
00662 {
00663    // Static method to unlock the main thread mutex.
00664 
00665    return (fgMainMutex ? fgMainMutex->UnLock() : 0);
00666 }
00667 
00668 //______________________________________________________________________________
00669 void *TThread::Function(void *ptr)
00670 {
00671    // Static method which is called by the system thread function and
00672    // which in turn calls the actual user function.
00673 
00674    TThread *th;
00675    void *ret, *arg;
00676 
00677    TThreadCleaner dummy;
00678 
00679    th = (TThread *)ptr;
00680 
00681    // Default cancel state is OFF
00682    // Default cancel type  is DEFERRED
00683    // User can change it by call SetCancelOn() and SetCancelAsynchronous()
00684    SetCancelOff();
00685    SetCancelDeferred();
00686    CleanUpPush((void *)&AfterCancel, th);  // Enable standard cancelling function
00687 
00688    if (gDebug)
00689       th->Info("TThread::Function", "thread is running");
00690 
00691    arg = th->fThreadArg;
00692    th->fState = kRunningState;
00693 
00694    if (th->fDetached) {
00695       //Detached, non joinable thread
00696       (th->fFcnVoid)(arg);
00697       ret = 0;
00698       th->fState = kFinishedState;
00699    } else {
00700       //UnDetached, joinable thread
00701       ret = (th->fFcnRetn)(arg);
00702       th->fState = kTerminatedState;
00703    }
00704 
00705    CleanUpPop(1);     // Disable standard canceling function
00706 
00707    if (gDebug)
00708       th->Info("TThread::Function", "thread has finished");
00709 
00710    TThread::Exit(ret);
00711 
00712    return ret;
00713 }
00714 
00715 //______________________________________________________________________________
00716 void TThread::Ps()
00717 {
00718    // Static method listing the existing threads.
00719 
00720    TThread *l;
00721    int i;
00722 
00723    if (!fgMain) {
00724       ::Info("TThread::Ps", "no threads have been created");
00725       return;
00726    }
00727 
00728    Lock();
00729 
00730    int num = 0;
00731    for (l = fgMain; l; l = l->fNext)
00732       num++;
00733 
00734    char cbuf[256];
00735    printf("     Thread                   State\n");
00736    for (l = fgMain; l; l = l->fNext) { // loop over threads
00737       memset(cbuf, ' ', sizeof(cbuf));
00738       snprintf(cbuf, sizeof(cbuf), "%3d  %s:0x%lx", num--, l->GetName(), l->fId);
00739       i = strlen(cbuf);
00740       if (i < 30)
00741          cbuf[i] = ' ';
00742       cbuf[30] = 0;
00743       printf("%30s", cbuf);
00744 
00745       switch (l->fState) {   // print states
00746          case kNewState:        printf("Idle       "); break;
00747          case kRunningState:    printf("Running    "); break;
00748          case kTerminatedState: printf("Terminated "); break;
00749          case kFinishedState:   printf("Finished   "); break;
00750          case kCancelingState:  printf("Canceling  "); break;
00751          case kCanceledState:   printf("Canceled   "); break;
00752          case kDeletingState:   printf("Deleting   "); break;
00753          default:               printf("Invalid    ");
00754       }
00755       if (l->fComment[0]) printf("  // %s", l->fComment);
00756       printf("\n");
00757    }  // end of loop
00758 
00759    UnLock();
00760 }
00761 
00762 //______________________________________________________________________________
00763 void **TThread::Tsd(void *dflt, Int_t k)
00764 {
00765    // Static method returning a pointer to thread specific data container
00766    // of the calling thread.
00767 
00768    TThread *th = TThread::Self();
00769 
00770    if (!th) {   //Main thread
00771       return (void**)dflt;
00772    } else {
00773       return &(th->fTsd[k]);
00774    }
00775 }
00776 
00777 //______________________________________________________________________________
00778 void TThread::Printf(const char *va_(fmt), ...)
00779 {
00780    // Static method providing a thread safe printf. Appends a newline.
00781 
00782    va_list ap;
00783    va_start(ap,va_(fmt));
00784 
00785    Int_t buf_size = 2048;
00786    char *buf;
00787 
00788 again:
00789    buf = new char[buf_size];
00790 
00791    int n = vsnprintf(buf, buf_size, va_(fmt), ap);
00792    // old vsnprintf's return -1 if string is truncated new ones return
00793    // total number of characters that would have been written
00794    if (n == -1 || n >= buf_size) {
00795       buf_size *= 2;
00796       delete [] buf;
00797       goto again;
00798    }
00799 
00800    va_end(ap);
00801 
00802    void *arr[2];
00803    arr[1] = (void*) buf;
00804    if (XARequest("PRTF", 2, arr, 0)) return;
00805 
00806    printf("%s\n", buf);
00807    fflush(stdout);
00808 
00809    delete [] buf;
00810 }
00811 
00812 //______________________________________________________________________________
00813 void TThread::ErrorHandler(int level, const char *location, const char *fmt,
00814                            va_list ap) const
00815 {
00816    // Thread specific error handler function.
00817    // It calls the user set error handler in the main thread.
00818 
00819    Int_t buf_size = 2048;
00820    char *buf, *bp;
00821 
00822 again:
00823    buf = new char[buf_size];
00824 
00825    int n = vsnprintf(buf, buf_size, fmt, ap);
00826    // old vsnprintf's return -1 if string is truncated new ones return
00827    // total number of characters that would have been written
00828    if (n == -1 || n >= buf_size) {
00829       buf_size *= 2;
00830       delete [] buf;
00831       goto again;
00832    }
00833    if (level >= kSysError && level < kFatal) {
00834       char *buf1 = new char[buf_size + strlen(gSystem->GetError()) + 5];
00835       sprintf(buf1, "%s (%s)", buf, gSystem->GetError());
00836       bp = buf1;
00837       delete [] buf;
00838    } else
00839       bp = buf;
00840 
00841    void *arr[4];
00842    arr[1] = (void*) Long_t(level);
00843    arr[2] = (void*) location;
00844    arr[3] = (void*) bp;
00845    if (XARequest("ERRO", 4, arr, 0)) return;
00846 
00847    if (level != kFatal)
00848       ::GetErrorHandler()(level, level >= gErrorAbortLevel, location, bp);
00849    else
00850       ::GetErrorHandler()(level, kTRUE, location, bp);
00851 
00852    delete [] bp;
00853 }
00854 
00855 //______________________________________________________________________________
00856 void TThread::DoError(int level, const char *location, const char *fmt,
00857                       va_list va) const
00858 {
00859    // Interface to ErrorHandler. User has to specify the class name as
00860    // part of the location, just like for the global Info(), Warning() and
00861    // Error() functions.
00862 
00863    char *loc = 0;
00864 
00865    if (location) {
00866       loc = new char[strlen(location) + strlen(GetName()) + 32];
00867       sprintf(loc, "%s %s:0x%lx", location, GetName(), fId);
00868    } else {
00869       loc = new char[strlen(GetName()) + 32];
00870       sprintf(loc, "%s:0x%lx", GetName(), fId);
00871    }
00872 
00873    ErrorHandler(level, loc, fmt, va);
00874 
00875    delete [] loc;
00876 }
00877 
00878 //______________________________________________________________________________
00879 Int_t TThread::XARequest(const char *xact, Int_t nb, void **ar, Int_t *iret)
00880 {
00881    // Static method used to allow commands to be executed by the main thread.
00882 
00883    if (!gApplication || !gApplication->IsRunning()) return 0;
00884 
00885    // The first time, create the related static vars
00886    if (!fgXActMutex && gGlobalMutex) {
00887       gGlobalMutex->Lock();
00888       if (!fgXActMutex) {
00889          fgXActMutex = new TMutex(kTRUE);
00890          fgXActCondi = new TCondition;
00891          new TThreadTimer;
00892       }
00893       gGlobalMutex->UnLock();
00894    }
00895 
00896    TThread *th = Self();
00897    if (th && th->fId != fgMainId) {   // we are in the thread
00898       th->SetComment("XARequest: XActMutex Locking");
00899       fgXActMutex->Lock();
00900       th->SetComment("XARequest: XActMutex Locked");
00901 
00902       TConditionImp *condimp = fgXActCondi->fConditionImp;
00903       TMutexImp *condmutex = fgXActCondi->GetMutex()->fMutexImp;
00904 
00905       // Lock now, so the XAction signal will wait
00906       // and never come before the wait
00907       condmutex->Lock();
00908 
00909       fgXAnb = nb;
00910       fgXArr = ar;
00911       fgXArt = 0;
00912       fgXAct = (char*) xact;
00913       th->SetComment(fgXAct);
00914 
00915       if (condimp) condimp->Wait();
00916       condmutex->UnLock();
00917 
00918       if (iret) *iret = fgXArt;
00919       fgXActMutex->UnLock();
00920       th->SetComment();
00921       return 1997;
00922    } else            //we are in the main thread
00923       return 0;
00924 }
00925 
00926 //______________________________________________________________________________
00927 void TThread::XAction()
00928 {
00929    // Static method called via the thread timer to execute in the main
00930    // thread certain commands. This to avoid sophisticated locking and
00931    // possible deadlocking.
00932 
00933    TConditionImp *condimp = fgXActCondi->fConditionImp;
00934    TMutexImp *condmutex = fgXActCondi->GetMutex()->fMutexImp;
00935    condmutex->Lock();
00936 
00937    char const acts[] = "PRTF CUPD CANV CDEL PDCD METH ERRO";
00938    enum { kPRTF = 0, kCUPD = 5, kCANV = 10, kCDEL = 15,
00939           kPDCD = 20, kMETH = 25, kERRO = 30 };
00940    int iact = strstr(acts, fgXAct) - acts;
00941    char *cmd = 0;
00942 
00943    switch (iact) {
00944 
00945       case kPRTF:
00946          printf("%s\n", (const char*)fgXArr[1]);
00947          fflush(stdout);
00948          break;
00949 
00950       case kERRO:
00951          {
00952             int level = (int)Long_t(fgXArr[1]);
00953             const char *location = (const char*)fgXArr[2];
00954             char *mess = (char*)fgXArr[3];
00955             if (level != kFatal)
00956                GetErrorHandler()(level, level >= gErrorAbortLevel, location, mess);
00957             else
00958                GetErrorHandler()(level, kTRUE, location, mess);
00959             delete [] mess;
00960          }
00961          break;
00962 
00963       case kCUPD:
00964          //((TCanvas *)fgXArr[1])->Update();
00965          cmd = Form("((TCanvas *)0x%lx)->Update();",(Long_t)fgXArr[1]);
00966          gROOT->ProcessLine(cmd);
00967          break;
00968 
00969       case kCANV:
00970 
00971          switch(fgXAnb) { // Over TCanvas constructors
00972 
00973             case 2:
00974                //((TCanvas*)fgXArr[1])->Constructor();
00975                cmd = Form("((TCanvas *)0x%lx)->Constructor();",(Long_t)fgXArr[1]);
00976                gROOT->ProcessLine(cmd);
00977                break;
00978 
00979             case 5:
00980                //((TCanvas*)fgXArr[1])->Constructor(
00981                //                 (char*)fgXArr[2],
00982                //                 (char*)fgXArr[3],
00983                //                *((Int_t*)(fgXArr[4])));
00984                cmd = Form("((TCanvas *)0x%lx)->Constructor((char*)0x%lx,(char*)0x%lx,*((Int_t*)(0x%lx)));",(Long_t)fgXArr[1],(Long_t)fgXArr[2],(Long_t)fgXArr[3],(Long_t)fgXArr[4]);
00985                gROOT->ProcessLine(cmd);
00986                break;
00987             case 6:
00988                //((TCanvas*)fgXArr[1])->Constructor(
00989                //                 (char*)fgXArr[2],
00990                //                 (char*)fgXArr[3],
00991                //                *((Int_t*)(fgXArr[4])),
00992                //                *((Int_t*)(fgXArr[5])));
00993                cmd = Form("((TCanvas *)0x%lx)->Constructor((char*)0x%lx,(char*)0x%lx,*((Int_t*)(0x%lx)),*((Int_t*)(0x%lx)));",(Long_t)fgXArr[1],(Long_t)fgXArr[2],(Long_t)fgXArr[3],(Long_t)fgXArr[4],(Long_t)fgXArr[5]);
00994                gROOT->ProcessLine(cmd);
00995                break;
00996 
00997             case 8:
00998                //((TCanvas*)fgXArr[1])->Constructor(
00999                //                 (char*)fgXArr[2],
01000                //                 (char*)fgXArr[3],
01001                //               *((Int_t*)(fgXArr[4])),
01002                //               *((Int_t*)(fgXArr[5])),
01003                //               *((Int_t*)(fgXArr[6])),
01004                //               *((Int_t*)(fgXArr[7])));
01005                cmd = Form("((TCanvas *)0x%lx)->Constructor((char*)0x%lx,(char*)0x%lx,*((Int_t*)(0x%lx)),*((Int_t*)(0x%lx)),*((Int_t*)(0x%lx)),*((Int_t*)(0x%lx)));",(Long_t)fgXArr[1],(Long_t)fgXArr[2],(Long_t)fgXArr[3],(Long_t)fgXArr[4],(Long_t)fgXArr[5],(Long_t)fgXArr[6],(Long_t)fgXArr[7]);
01006                gROOT->ProcessLine(cmd);
01007                break;
01008 
01009          }
01010          break;
01011 
01012       case kCDEL:
01013          //((TCanvas*)fgXArr[1])->Destructor();
01014          cmd = Form("((TCanvas *)0x%lx)->Destructor();",(Long_t)fgXArr[1]);
01015          gROOT->ProcessLine(cmd);
01016          break;
01017 
01018       case kPDCD:
01019          ((TVirtualPad*) fgXArr[1])->Divide( *((Int_t*)(fgXArr[2])),
01020                                   *((Int_t*)(fgXArr[3])),
01021                                   *((Float_t*)(fgXArr[4])),
01022                                   *((Float_t*)(fgXArr[5])),
01023                                   *((Int_t*)(fgXArr[6])));
01024          break;
01025       case kMETH:
01026          ((TMethodCall *) fgXArr[1])->Execute((void*)(fgXArr[2]),(const char*)(fgXArr[3]));
01027          break;
01028 
01029       default:
01030          ::Error("TThread::XAction", "wrong case");
01031    }
01032 
01033    fgXAct = 0;
01034    if (condimp) condimp->Signal();
01035    condmutex->UnLock();
01036 }
01037 
01038 
01039 //////////////////////////////////////////////////////////////////////////
01040 //                                                                      //
01041 // TThreadTimer                                                         //
01042 //                                                                      //
01043 //////////////////////////////////////////////////////////////////////////
01044 
01045 //______________________________________________________________________________
01046 TThreadTimer::TThreadTimer(Long_t ms) : TTimer(ms, kTRUE)
01047 {
01048    // Create thread timer.
01049 
01050    gSystem->AddTimer(this);
01051 }
01052 
01053 //______________________________________________________________________________
01054 Bool_t TThreadTimer::Notify()
01055 {
01056    // Periodically execute the TThread::XAxtion() method in the main thread.
01057 
01058    if (TThread::fgXAct) { TThread::XAction(); }
01059    Reset();
01060 
01061    return kFALSE;
01062 }
01063 
01064 
01065 //////////////////////////////////////////////////////////////////////////
01066 //                                                                      //
01067 //  TThreadCleaner                                                      //
01068 //                                                                      //
01069 //////////////////////////////////////////////////////////////////////////
01070 
01071 //______________________________________________________________________________
01072 TThreadCleaner::~TThreadCleaner()
01073 {
01074    // Call user clean up routines.
01075 
01076    TThread::CleanUp();
01077 }

Generated on Tue Jul 5 14:12:02 2011 for ROOT_528-00b_version by  doxygen 1.5.1