00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00086
00087 fH = new TThread("JoinHelper", JoinFunc, this);
00088 }
00089
00090
00091 TJoinHelper::~TJoinHelper()
00092 {
00093
00094
00095 delete fC;
00096 delete fM;
00097 delete fH;
00098 }
00099
00100
00101 void TJoinHelper::JoinFunc(void *p)
00102 {
00103
00104
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
00121
00122 fM->Lock();
00123 fH->Run();
00124
00125 while (kTRUE) {
00126 int r = fC->TimedWaitRelative(100);
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
00149
00150
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
00166
00167
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
00183
00184
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
00200
00201
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
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
00235
00236
00237 if (fgThreadImp) return kTRUE;
00238 else return kFALSE;
00239 }
00240
00241
00242 void TThread::Init()
00243 {
00244
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
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
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;
00278
00279 if (fgMain) fgMain->fPrev = this;
00280 fNext = fgMain; fPrev = 0; fgMain = this;
00281
00282 UnLock();
00283 SetComment();
00284
00285
00286 }
00287
00288
00289 TThread::~TThread()
00290 {
00291
00292
00293 if (gDebug)
00294 Info("TThread::~TThread", "thread deleted");
00295
00296
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
00315
00316 if (!th) return 0;
00317 th->fHolder = &th;
00318
00319 if (th->fState == kRunningState) {
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
00337
00338
00339 Lock();
00340
00341 Int_t num = 0;
00342 for (TThread *l = fgMain; l; l = l->fNext)
00343 num++;
00344
00345 UnLock();
00346
00347 return num;
00348 }
00349
00350
00351 void TThread::SetPriority(EPriority pri)
00352 {
00353
00354
00355 fPriority = pri;
00356 }
00357
00358
00359 TThread *TThread::GetThread(Long_t id)
00360 {
00361
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
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
00394
00395 return GetThread(SelfId());
00396 }
00397
00398
00399
00400 Long_t TThread::Join(void **ret)
00401 {
00402
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
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
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
00442
00443 if (!fgThreadImp) Init();
00444
00445 return fgThreadImp->SelfId();
00446 }
00447
00448
00449 Int_t TThread::Run(void *arg)
00450 {
00451
00452
00453
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
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
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
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
00522
00523 return fgThreadImp->SetCancelOff();
00524 }
00525
00526
00527 Int_t TThread::SetCancelOn()
00528 {
00529
00530
00531 return fgThreadImp->SetCancelOn();
00532 }
00533
00534
00535 Int_t TThread::SetCancelAsynchronous()
00536 {
00537
00538
00539 return fgThreadImp->SetCancelAsynchronous();
00540 }
00541
00542
00543 Int_t TThread::SetCancelDeferred()
00544 {
00545
00546
00547 return fgThreadImp->SetCancelDeferred();
00548 }
00549
00550
00551 Int_t TThread::CancelPoint()
00552 {
00553
00554
00555 return fgThreadImp->CancelPoint();
00556 }
00557
00558
00559 Int_t TThread::CleanUpPush(void *free, void *arg)
00560 {
00561
00562
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
00574
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
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
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
00618
00619 return fgThreadImp->Exit(ret);
00620 }
00621
00622
00623 Int_t TThread::Sleep(ULong_t secs, ULong_t nanos)
00624 {
00625
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
00636
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
00648
00649 return (fgMainMutex ? fgMainMutex->Lock() : 0);
00650 }
00651
00652
00653 Int_t TThread::TryLock()
00654 {
00655
00656
00657 return (fgMainMutex ? fgMainMutex->TryLock() : 0);
00658 }
00659
00660
00661 Int_t TThread::UnLock()
00662 {
00663
00664
00665 return (fgMainMutex ? fgMainMutex->UnLock() : 0);
00666 }
00667
00668
00669 void *TThread::Function(void *ptr)
00670 {
00671
00672
00673
00674 TThread *th;
00675 void *ret, *arg;
00676
00677 TThreadCleaner dummy;
00678
00679 th = (TThread *)ptr;
00680
00681
00682
00683
00684 SetCancelOff();
00685 SetCancelDeferred();
00686 CleanUpPush((void *)&AfterCancel, th);
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
00696 (th->fFcnVoid)(arg);
00697 ret = 0;
00698 th->fState = kFinishedState;
00699 } else {
00700
00701 ret = (th->fFcnRetn)(arg);
00702 th->fState = kTerminatedState;
00703 }
00704
00705 CleanUpPop(1);
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
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) {
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) {
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 }
00758
00759 UnLock();
00760 }
00761
00762
00763 void **TThread::Tsd(void *dflt, Int_t k)
00764 {
00765
00766
00767
00768 TThread *th = TThread::Self();
00769
00770 if (!th) {
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
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
00793
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
00817
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
00827
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
00860
00861
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
00882
00883 if (!gApplication || !gApplication->IsRunning()) return 0;
00884
00885
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) {
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
00906
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
00923 return 0;
00924 }
00925
00926
00927 void TThread::XAction()
00928 {
00929
00930
00931
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
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) {
00972
00973 case 2:
00974
00975 cmd = Form("((TCanvas *)0x%lx)->Constructor();",(Long_t)fgXArr[1]);
00976 gROOT->ProcessLine(cmd);
00977 break;
00978
00979 case 5:
00980
00981
00982
00983
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
00989
00990
00991
00992
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
00999
01000
01001
01002
01003
01004
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
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
01042
01043
01044
01045
01046 TThreadTimer::TThreadTimer(Long_t ms) : TTimer(ms, kTRUE)
01047 {
01048
01049
01050 gSystem->AddTimer(this);
01051 }
01052
01053
01054 Bool_t TThreadTimer::Notify()
01055 {
01056
01057
01058 if (TThread::fgXAct) { TThread::XAction(); }
01059 Reset();
01060
01061 return kFALSE;
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072 TThreadCleaner::~TThreadCleaner()
01073 {
01074
01075
01076 TThread::CleanUp();
01077 }