23 #include "RConfigure.h"
41 TThreadImp *TThread::fgThreadImp = 0;
42 Long_t TThread::fgMainId = 0;
43 TThread *TThread::fgMain = 0;
44 TMutex *TThread::fgMainMutex;
45 char *
volatile TThread::fgXAct = 0;
46 TMutex *TThread::fgXActMutex = 0;
47 TCondition *TThread::fgXActCondi = 0;
48 void **
volatile TThread::fgXArr = 0;
49 volatile Int_t TThread::fgXAnb = 0;
50 volatile Int_t TThread::fgXArt = 0;
52 static void CINT_alloc_lock() { gGlobalMutex->Lock(); }
53 static void CINT_alloc_unlock() { gGlobalMutex->UnLock(); }
55 static TMutex *gMainInternalMutex = 0;
57 static void ThreadInternalLock() {
if (gMainInternalMutex) gMainInternalMutex->Lock(); }
58 static void ThreadInternalUnLock() {
if (gMainInternalMutex) gMainInternalMutex->UnLock(); }
60 static Bool_t fgIsTearDown(kFALSE);
62 extern "C" void ROOT_TThread_Initialize()
64 TThread::Initialize();
70 class TThreadTearDownGuard {
72 TThreadTearDownGuard() { fgIsTearDown = kFALSE; }
73 ~TThreadTearDownGuard() {
80 TVirtualMutex *m = gGlobalMutex;
83 TThreadImp *imp = TThread::fgThreadImp;
84 TThread::fgThreadImp = 0;
88 static TThreadTearDownGuard gTearDownGuard;
102 static void* JoinFunc(
void *p);
105 TJoinHelper(TThread *th,
void **ret);
114 TJoinHelper::TJoinHelper(TThread *th,
void **ret)
115 : fT(th), fRet(ret), fRc(0), fM(new TMutex), fC(new TCondition(fM)), fJoined(kFALSE)
117 fH =
new TThread(
"JoinHelper", JoinFunc,
this);
123 TJoinHelper::~TJoinHelper()
135 void* TJoinHelper::JoinFunc(
void *p)
137 TJoinHelper *jp = (TJoinHelper*)p;
139 jp->fRc = jp->fT->Join(jp->fRet);
154 Int_t TJoinHelper::Join()
162 int r = fC->TimedWaitRelative(100);
174 if (r == 0 || r == 1) {
182 gSystem->ProcessEvents();
189 TThread::fgThreadImp->Join(fH, 0);
205 TThread::TThread(VoidRtnFunc_t fn,
void *arg, EPriority pri)
206 : TNamed(
"<anon>",
"")
222 TThread::TThread(VoidFunc_t fn,
void *arg, EPriority pri)
223 : TNamed(
"<anon>",
"")
239 TThread::TThread(
const char *thname, VoidRtnFunc_t fn,
void *arg,
240 EPriority pri) : TNamed(thname,
"")
256 TThread::TThread(
const char *thname, VoidFunc_t fn,
void *arg,
257 EPriority pri) : TNamed(thname,
"")
271 TThread::TThread(Long_t
id)
276 fPriority = kNormalPriority;
282 ThreadInternalLock();
284 fId = (
id ?
id : SelfId());
285 fState = kRunningState;
286 ThreadInternalUnLock();
289 Info(
"TThread::TThread",
"TThread attached to running thread");
297 void TThread::Initialize()
306 Bool_t TThread::IsInitialized()
318 if (fgThreadImp || fgIsTearDown)
return;
320 #if !defined (_REENTRANT) && !defined (WIN32)
322 ::Fatal(
"Init",
"_REENTRANT must be #define-d for TThread to work properly.");
329 fgThreadImp = gThreadFactory->CreateThreadImp();
330 gMainInternalMutex =
new TMutex(kTRUE);
332 fgMainId = fgThreadImp->SelfId();
333 fgMainMutex =
new TMutex(kTRUE);
334 gThreadTsd = TThread::Tsd;
335 gThreadXAR = TThread::XARequest;
339 gGlobalMutex =
new TMutex(kTRUE);
341 TInterpreter::Instance()->SetAlloclockfunc(CINT_alloc_lock);
342 gCling->SetAllocunlockfunc(CINT_alloc_unlock);
348 R__LOCKGUARD(gGlobalMutex);
349 if (!ROOT::gCoreMutex) {
352 ROOT::gCoreMutex =
new ROOT::TRWMutexImp<std::mutex, ROOT::Internal::RecurseCounts>();
354 gInterpreterMutex = ROOT::gCoreMutex;
355 gROOTMutex = gInterpreterMutex;
362 void TThread::Constructor()
370 if (!fgThreadImp) Init();
372 SetComment(
"Constructor: MainInternalMutex Locking");
373 ThreadInternalLock();
374 SetComment(
"Constructor: MainInternalMutex Locked");
376 if (fgMain) fgMain->fPrev =
this;
377 fNext = fgMain; fPrev = 0; fgMain =
this;
379 ThreadInternalUnLock();
391 Info(
"TThread::~TThread",
"thread deleted");
395 SetComment(
"Destructor: MainInternalMutex Locking");
396 ThreadInternalLock();
397 SetComment(
"Destructor: MainInternalMutex Locked");
399 if (fPrev) fPrev->fNext = fNext;
400 if (fNext) fNext->fPrev = fPrev;
401 if (fgMain ==
this) fgMain = fNext;
403 ThreadInternalUnLock();
405 if (fHolder) *fHolder = 0;
414 Int_t TThread::Delete(TThread *&th)
419 if (th->fState == kRunningState) {
420 th->fState = kDeletingState;
423 th->Info(
"TThread::Delete",
"deleting thread");
437 Int_t TThread::Exists()
439 ThreadInternalLock();
442 for (TThread *l = fgMain; l; l = l->fNext)
445 ThreadInternalUnLock();
453 void TThread::SetPriority(EPriority pri)
461 TThread *TThread::GetThread(Long_t
id)
465 ThreadInternalLock();
467 for (myTh = fgMain; myTh && (myTh->fId != id); myTh = myTh->fNext) { }
469 ThreadInternalUnLock();
477 TThread *TThread::GetThread(
const char *name)
481 ThreadInternalLock();
483 for (myTh = fgMain; myTh && (strcmp(name, myTh->GetName())); myTh = myTh->fNext) { }
485 ThreadInternalUnLock();
493 TThread *TThread::Self()
495 TTHREAD_TLS(TThread*) self = 0;
497 if (!self || fgIsTearDown) {
498 if (fgIsTearDown)
self = 0;
499 self = GetThread(SelfId());
508 Long_t TThread::Join(
void **ret)
511 Error(
"Join",
"thread not running");
516 Error(
"Join",
"cannot join detached thread");
520 if (SelfId() != fgMainId)
521 return fgThreadImp->Join(
this, ret);
524 TJoinHelper helper(
this, ret);
526 return helper.Join();
532 Long_t TThread::Join(Long_t jid,
void **ret)
534 TThread *myTh = GetThread(jid);
537 ::Error(
"TThread::Join",
"cannot find thread 0x%lx", jid);
541 return myTh->Join(ret);
547 Long_t TThread::SelfId()
549 if (fgIsTearDown)
return -1;
550 if (!fgThreadImp) Init();
552 return fgThreadImp->SelfId();
561 Int_t TThread::Run(
void *arg)
563 if (arg) fThreadArg = arg;
565 SetComment(
"Run: MainInternalMutex locking");
566 ThreadInternalLock();
567 SetComment(
"Run: MainMutex locked");
569 int iret = fgThreadImp->Run(
this);
571 fState = iret ? kInvalidState : kRunningState;
574 Info(
"TThread::Run",
"thread run requested");
576 ThreadInternalUnLock();
585 Int_t TThread::Kill()
587 if (fState != kRunningState && fState != kDeletingState) {
589 Warning(
"TThread::Kill",
"thread is not running");
592 if (fState == kRunningState ) fState = kCancelingState;
593 return fgThreadImp->Kill(
this);
601 Int_t TThread::Kill(Long_t
id)
603 TThread *th = GetThread(
id);
605 return fgThreadImp->Kill(th);
608 ::Warning(
"TThread::Kill(Long_t)",
"thread 0x%lx not found",
id);
617 Int_t TThread::Kill(
const char *name)
619 TThread *th = GetThread(name);
621 return fgThreadImp->Kill(th);
624 ::Warning(
"TThread::Kill(const char*)",
"thread %s not found", name);
633 Int_t TThread::SetCancelOff()
635 return fgThreadImp ? fgThreadImp->SetCancelOff() : -1;
642 Int_t TThread::SetCancelOn()
644 return fgThreadImp ? fgThreadImp->SetCancelOn() : -1;
652 Int_t TThread::SetCancelAsynchronous()
654 return fgThreadImp ? fgThreadImp->SetCancelAsynchronous() : -1;
662 Int_t TThread::SetCancelDeferred()
664 return fgThreadImp ? fgThreadImp->SetCancelDeferred() : -1;
671 Int_t TThread::CancelPoint()
673 return fgThreadImp ? fgThreadImp->CancelPoint() : -1;
680 Int_t TThread::CleanUpPush(
void *free,
void *arg)
682 TThread *th = Self();
684 return fgThreadImp->CleanUpPush(&(th->fClean), free, arg);
692 Int_t TThread::CleanUpPop(Int_t exe)
694 TThread *th = Self();
696 return fgThreadImp->CleanUpPop(&(th->fClean), exe);
703 Int_t TThread::CleanUp()
705 TThread *th = Self();
708 fgThreadImp->CleanUp(&(th->fClean));
709 fgMainMutex->CleanUp();
711 fgXActMutex->CleanUp();
713 gMainInternalMutex->CleanUp();
724 void TThread::AfterCancel(TThread *th)
727 th->fState = kCanceledState;
729 th->Info(
"TThread::AfterCancel",
"thread is canceled");
731 ::Error(
"TThread::AfterCancel",
"zero thread pointer passed");
737 Int_t TThread::Exit(
void *ret)
739 return fgThreadImp ? fgThreadImp->Exit(ret) : -1;
745 Int_t TThread::Sleep(ULong_t secs, ULong_t nanos)
747 UInt_t ms = UInt_t(secs * 1000) + UInt_t(nanos / 1000000);
748 if (gSystem) gSystem->Sleep(ms);
756 Int_t TThread::GetTime(ULong_t *absSec, ULong_t *absNanoSec)
759 if (absSec) *absSec = t.GetSec();
760 if (absNanoSec) *absNanoSec = t.GetNanoSec();
767 Int_t TThread::Lock()
769 return (fgMainMutex ? fgMainMutex->Lock() : 0);
775 Int_t TThread::TryLock()
777 return (fgMainMutex ? fgMainMutex->TryLock() : 0);
783 Int_t TThread::UnLock()
785 return (fgMainMutex ? fgMainMutex->UnLock() : 0);
792 void *TThread::Function(
void *ptr)
797 TThreadCleaner dummy;
806 CleanUpPush((
void *)&AfterCancel, th);
809 th->Info(
"TThread::Function",
"thread is running");
811 arg = th->fThreadArg;
812 th->fState = kRunningState;
818 th->fState = kFinishedState;
821 ret = (th->fFcnRetn)(arg);
822 th->fState = kTerminatedState;
828 th->Info(
"TThread::Function",
"thread has finished");
844 ::Info(
"TThread::Ps",
"no threads have been created");
848 ThreadInternalLock();
851 for (l = fgMain; l; l = l->fNext)
855 printf(
" Thread State\n");
856 for (l = fgMain; l; l = l->fNext) {
857 memset(cbuf,
' ',
sizeof(cbuf));
858 snprintf(cbuf,
sizeof(cbuf),
"%3d %s:0x%lx", num--, l->GetName(), l->fId);
863 printf(
"%30s", cbuf);
866 case kNewState: printf(
"Idle ");
break;
867 case kRunningState: printf(
"Running ");
break;
868 case kTerminatedState: printf(
"Terminated ");
break;
869 case kFinishedState: printf(
"Finished ");
break;
870 case kCancelingState: printf(
"Canceling ");
break;
871 case kCanceledState: printf(
"Canceled ");
break;
872 case kDeletingState: printf(
"Deleting ");
break;
873 default: printf(
"Invalid ");
875 if (l->fComment[0]) printf(
" // %s", l->fComment);
879 ThreadInternalUnLock();
889 void **TThread::Tsd(
void *dflt, Int_t k)
891 if (TThread::SelfId() == fgMainId) {
902 void **TThread::GetTls(Int_t k) {
903 TTHREAD_TLS_ARRAY(
void*, ROOT::kMaxThreadSlot, tls);
910 if (k == ROOT::kDirectoryThreadSlot && tls[k] ==
nullptr)
919 void TThread::Printf(
const char *va_(fmt), ...)
922 va_start(ap,va_(fmt));
924 Int_t buf_size = 2048;
928 buf =
new char[buf_size];
930 int n = vsnprintf(buf, buf_size, va_(fmt), ap);
933 if (n == -1 || n >= buf_size) {
942 arr[1] = (
void*) buf;
943 if (XARequest(
"PRTF", 2, arr, 0))
return;
955 void TThread::ErrorHandler(
int level,
const char *location,
const char *fmt,
958 Int_t buf_size = 2048;
962 buf =
new char[buf_size];
964 int n = vsnprintf(buf, buf_size, fmt, ap);
967 if (n == -1 || n >= buf_size) {
972 if (level >= kSysError && level < kFatal) {
973 char *buf1 =
new char[buf_size + strlen(gSystem->GetError()) + 5];
974 sprintf(buf1,
"%s (%s)", buf, gSystem->GetError());
981 arr[1] = (
void*) Long_t(level);
982 arr[2] = (
void*) location;
984 if (XARequest(
"ERRO", 4, arr, 0))
return;
987 ::GetErrorHandler()(level, level >= gErrorAbortLevel, location, bp);
989 ::GetErrorHandler()(level, kTRUE, location, bp);
999 void TThread::DoError(
int level,
const char *location,
const char *fmt,
1005 loc =
new char[strlen(location) + strlen(GetName()) + 32];
1006 sprintf(loc,
"%s %s:0x%lx", location, GetName(), fId);
1008 loc =
new char[strlen(GetName()) + 32];
1009 sprintf(loc,
"%s:0x%lx", GetName(), fId);
1012 ErrorHandler(level, loc, fmt, va);
1020 Int_t TThread::XARequest(
const char *xact, Int_t nb,
void **ar, Int_t *iret)
1022 if (!gApplication || !gApplication->IsRunning())
return 0;
1025 if (!fgXActMutex && gGlobalMutex) {
1026 gGlobalMutex->Lock();
1028 fgXActMutex =
new TMutex(kTRUE);
1029 fgXActCondi =
new TCondition;
1032 gGlobalMutex->UnLock();
1035 TThread *th = Self();
1036 if (th && th->fId != fgMainId) {
1037 th->SetComment(
"XARequest: XActMutex Locking");
1038 fgXActMutex->Lock();
1039 th->SetComment(
"XARequest: XActMutex Locked");
1041 TConditionImp *condimp = fgXActCondi->fConditionImp;
1042 TMutexImp *condmutex = fgXActCondi->GetMutex()->fMutexImp;
1051 fgXAct = (
char*) xact;
1052 th->SetComment(fgXAct);
1054 if (condimp) condimp->Wait();
1055 condmutex->UnLock();
1057 if (iret) *iret = fgXArt;
1058 fgXActMutex->UnLock();
1070 void TThread::XAction()
1072 TConditionImp *condimp = fgXActCondi->fConditionImp;
1073 TMutexImp *condmutex = fgXActCondi->GetMutex()->fMutexImp;
1076 char const acts[] =
"PRTF CUPD CANV CDEL PDCD METH ERRO";
1077 enum { kPRTF = 0, kCUPD = 5, kCANV = 10, kCDEL = 15,
1078 kPDCD = 20, kMETH = 25, kERRO = 30 };
1079 int iact = strstr(acts, fgXAct) - acts;
1085 printf(
"%s\n", (
const char*)fgXArr[1]);
1091 int level = (int)Long_t(fgXArr[1]);
1092 const char *location = (
const char*)fgXArr[2];
1093 char *mess = (
char*)fgXArr[3];
1094 if (level != kFatal)
1095 GetErrorHandler()(level, level >= gErrorAbortLevel, location, mess);
1097 GetErrorHandler()(level, kTRUE, location, mess);
1104 union CastFromFuncToVoidPtr_t {
1105 void (*fFuncPtr)(
void*);
1107 } castFromFuncToVoidPtr;
1108 castFromFuncToVoidPtr.fVoidPtr = fgXArr[2];
1109 (*castFromFuncToVoidPtr.fFuncPtr)(fgXArr[1]);
1118 cmd = Form(
"((TCanvas *)0x%lx)->Constructor();",(Long_t)fgXArr[1]);
1119 gROOT->ProcessLine(cmd);
1127 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]);
1128 gROOT->ProcessLine(cmd);
1136 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]);
1137 gROOT->ProcessLine(cmd);
1148 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]);
1149 gROOT->ProcessLine(cmd);
1157 cmd = Form(
"((TCanvas *)0x%lx)->Destructor();",(Long_t)fgXArr[1]);
1158 gROOT->ProcessLine(cmd);
1162 ((TVirtualPad*) fgXArr[1])->Divide( *((Int_t*)(fgXArr[2])),
1163 *((Int_t*)(fgXArr[3])),
1164 *((Float_t*)(fgXArr[4])),
1165 *((Float_t*)(fgXArr[5])),
1166 *((Int_t*)(fgXArr[6])));
1169 ((TMethodCall *) fgXArr[1])->Execute((
void*)(fgXArr[2]),(
const char*)(fgXArr[3]));
1173 ::Error(
"TThread::XAction",
"wrong case");
1177 if (condimp) condimp->Signal();
1178 condmutex->UnLock();
1191 TThreadTimer::TThreadTimer(Long_t ms) : TTimer(ms, kTRUE)
1193 gSystem->AddTimer(
this);
1199 Bool_t TThreadTimer::Notify()
1201 if (TThread::fgXAct) { TThread::XAction(); }
1217 TThreadCleaner::~TThreadCleaner()