Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TThread.cxx
Go to the documentation of this file.
1// @(#)root/thread:$Id$
2// Author: Fons Rademakers 02/07/97
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TThread
13
14\legacy{TThread}
15
16This class implements threads. A thread is an execution environment
17much lighter than a process. A single process can have multiple
18threads. The actual work is done via the TThreadImp class (either
19TPosixThread or TWin32Thread).
20
21**/
22
23#include "RConfigure.h"
24
25#include "TThread.h"
26#include "TThreadImp.h"
27#include "TThreadFactory.h"
28#include "TROOT.h"
29#include "TCondition.h"
30#include "TApplication.h"
31#include "TVirtualPad.h"
32#include "TMethodCall.h"
33#include "TMutex.h"
34#include "TTimeStamp.h"
35#include "TInterpreter.h"
36#include "TError.h"
37#include "TSystem.h"
38#include "Varargs.h"
39#include "ThreadLocalStorage.h"
40#include "TThreadSlots.h"
41#include "TRWMutexImp.h"
42#include "snprintf.h"
43
46TThread *TThread::fgMain = nullptr;
48std::atomic<char *> volatile TThread::fgXAct{nullptr};
51void **volatile TThread::fgXArr = nullptr;
52volatile Int_t TThread::fgXAnb = 0;
53volatile Int_t TThread::fgXArt = 0;
54
55static void CINT_alloc_lock() { gGlobalMutex->Lock(); }
57
58static TMutex *gMainInternalMutex = nullptr;
59
62
64
65extern "C" void ROOT_TThread_Initialize()
66{
68};
69
70//------------------------------------------------------------------------------
71
72// Set gGlobalMutex to 0 when Thread library gets unloaded
74public:
77 // Note: we could insert here a wait for all thread to be finished.
78 // this is questionable though as we need to balance between fixing a
79 // user error (the thread was let lose and the caller did not explicit wait)
80 // and the risk that we can not terminate a failing process.
81
84 gGlobalMutex = nullptr;
85 delete m;
87 TThread::fgThreadImp = nullptr;
88 delete imp;
89 }
90};
92
93//------------------------------------------------------------------------------
94
96private:
99 void **fRet;
104
105 static void* JoinFunc(void *p);
106
107public:
108 TJoinHelper(TThread *th, void **ret);
109 ~TJoinHelper();
110
111 Int_t Join();
112};
113
114////////////////////////////////////////////////////////////////////////////////
115/// Constructor of Thread helper class.
116
118 : fT(th), fRet(ret), fRc(0), fM(new TMutex), fC(new TCondition(fM)), fJoined(kFALSE)
119{
120 fH = new TThread("JoinHelper", JoinFunc, this);
121}
122
123////////////////////////////////////////////////////////////////////////////////
124/// Destructor.
125
127{
128 delete fC;
129 delete fM;
130 delete fH;
131}
132
133////////////////////////////////////////////////////////////////////////////////
134/// Static method which runs in a separate thread to handle thread
135/// joins without blocking the main thread.
136/// Return a value (zero) so that it makes a joinable thread.
137
139{
141
142 jp->fRc = jp->fT->Join(jp->fRet);
143
144 jp->fM->Lock();
145 jp->fJoined = kTRUE;
146 jp->fC->Signal();
147 jp->fM->UnLock();
148
149 TThread::Exit(nullptr);
150
151 return nullptr;
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Thread join function.
156
158{
159 fM->Lock();
160 fH->Run();
161
162 while (kTRUE) {
163 // TimedWaitRelative will release the mutex (i.e. equivalent to fM->Unlock),
164 // then block on the condition variable. Upon return it will lock the mutex.
165 int r = fC->TimedWaitRelative(100); // 100 ms
166
167 // From the man page from pthread_ond_timedwait:
168
169 // When using condition variables there is always a Boolean predicate
170 // involving shared variables associated with each condition wait that
171 // is true if the thread should proceed. Spurious wakeups from the
172 // pthread_cond_timedwait() or pthread_cond_wait() functions may occur.
173 // Since the return from pthread_cond_timedwait() or pthread_cond_wait()
174 // does not imply anything about the value of this predicate, the
175 // predicate should be re-evaluated upon such return.
176
177 if (r == 0 || r == 1) {
178 // If we received the signal or timed out, let's check the value
179 if (fJoined) break;
180 } else {
181 // If any other error occurred, there is no point in trying again
182 break;
183 }
184
186 }
187
188 fM->UnLock();
189
190 // And wait for the help to finish to avoid the risk that it is still
191 // running when the main tread is finished (and the thread library unloaded!)
192 TThread::fgThreadImp->Join(fH, nullptr);
193
194 return fRc;
195}
196
197
198//------------------------------------------------------------------------------
199
200
201
202////////////////////////////////////////////////////////////////////////////////
203/// Create a thread. Specify the function or static class method
204/// to be executed by the thread and a pointer to the argument structure.
205/// The user function should return a void*. To start the thread call Run().
206
207TThread::TThread(VoidRtnFunc_t fn, void *arg, EPriority pri)
208 : TNamed("<anon>", "")
209{
211 fFcnVoid = nullptr;
212 fFcnRetn = fn;
213 fPriority = pri;
214 fThreadArg = arg;
215 Constructor();
216 fNamed = kFALSE;
217}
218
219////////////////////////////////////////////////////////////////////////////////
220/// Create a detached thread. Specify the function or static class method
221/// to be executed by the thread and a pointer to the argument structure.
222/// To start the thread call Run().
223
224TThread::TThread(VoidFunc_t fn, void *arg, EPriority pri)
225 : TNamed("<anon>", "")
226{
228 fFcnRetn = nullptr;
229 fFcnVoid = fn;
230 fPriority = pri;
231 fThreadArg = arg;
232 Constructor();
233 fNamed = kFALSE;
234}
235
236////////////////////////////////////////////////////////////////////////////////
237/// Create thread with a name. Specify the function or static class method
238/// to be executed by the thread and a pointer to the argument structure.
239/// The user function should return a void*. To start the thread call Run().
240
241TThread::TThread(const char *thname, VoidRtnFunc_t fn, void *arg,
242 EPriority pri) : TNamed(thname, "")
243{
245 fFcnVoid = nullptr;
246 fFcnRetn = fn;
247 fPriority = pri;
248 fThreadArg = arg;
249 Constructor();
250 fNamed = kTRUE;
251}
252
253////////////////////////////////////////////////////////////////////////////////
254/// Create a detached thread with a name. Specify the function or static
255/// class method to be executed by the thread and a pointer to the argument
256/// structure. To start the thread call Run().
257
258TThread::TThread(const char *thname, VoidFunc_t fn, void *arg,
259 EPriority pri) : TNamed(thname, "")
260{
262 fFcnRetn = nullptr;
263 fFcnVoid = fn;
264 fPriority = pri;
265 fThreadArg = arg;
266 Constructor();
267 fNamed = kTRUE;
268}
269
270////////////////////////////////////////////////////////////////////////////////
271/// Create a TThread for a already running thread.
272
274{
276 fFcnRetn = nullptr;
277 fFcnVoid = nullptr;
279 fThreadArg = nullptr;
280 Constructor();
281
282 // Changing the id must be protected as it will be look at by multiple
283 // threads (see TThread::GetThread)
285 fNamed = kFALSE;
286 fId = (id ? id : SelfId());
289
290 if (gDebug)
291 Info("TThread::TThread", "TThread attached to running thread");
292}
293
294////////////////////////////////////////////////////////////////////////////////
295/// Initialize the Thread package. This initializes the TThread and ROOT
296/// global mutexes to make parts of ROOT thread safe/aware. This call is
297/// implicit in case a TThread is created.
298
300{
301 Init();
302}
303
304////////////////////////////////////////////////////////////////////////////////
305/// Return true, if the TThread objects have been initialize. If false,
306/// the process is (from ROOT's point of view) single threaded.
307
309{
310 if (fgThreadImp)
311 return kTRUE;
312 return kFALSE;
313}
314
315////////////////////////////////////////////////////////////////////////////////
316/// Initialize global state and variables once.
317
319{
320 if (fgThreadImp || fgIsTearDown) return;
321
322 // 'Insure' gROOT is created before initializing the Thread safe behavior
323 // (to make sure we do not have two attempting to create it).
325
328
329 fgMainId = fgThreadImp->SelfId();
330 fgMainMutex = new TMutex(kTRUE);
333
334
335 // Create the single global mutex
337 // We need to make sure that gCling is initialized.
338 TInterpreter::Instance()->SetAlloclockfunc(CINT_alloc_lock);
340
341 // To avoid deadlocks, gInterpreterMutex and gROOTMutex need
342 // to point at the same instance.
343 // Both are now deprecated in favor of ROOT::gCoreMutex
344 {
346 if (!ROOT::gCoreMutex) {
347 // To avoid dead locks, caused by shared library opening and/or static initialization
348 // taking the same lock as 'tls_get_addr_tail', we can not use UniqueLockRecurseCount.
349#ifdef R__HAS_TBB
351#else
353#endif
354 }
357 }
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// Common thread constructor.
362
364{
365 fHolder = nullptr;
366 fClean = nullptr;
368
369 fId = -1;
370 fHandle= 0;
371 if (!fgThreadImp) Init();
372
373 SetComment("Constructor: MainInternalMutex Locking");
375 SetComment("Constructor: MainInternalMutex Locked");
376
377 if (fgMain) fgMain->fPrev = this;
378 fNext = fgMain;
379 fPrev = nullptr;
380 fgMain = this;
381
383 SetComment();
384
385 // thread is set up in initialisation routine or Run().
386}
387
388////////////////////////////////////////////////////////////////////////////////
389/// Cleanup the thread.
390
392{
393 if (gDebug)
394 Info("TThread::~TThread", "thread deleted");
395
396 // Disconnect thread instance
397
398 SetComment("Destructor: MainInternalMutex Locking");
400 SetComment("Destructor: MainInternalMutex Locked");
401
402 if (fPrev) fPrev->fNext = fNext;
403 if (fNext) fNext->fPrev = fPrev;
404 if (fgMain == this) fgMain = fNext;
405
407 SetComment();
408 if (fHolder)
409 *fHolder = nullptr;
410}
411
412////////////////////////////////////////////////////////////////////////////////
413/// Static method to delete the specified thread.
414/// Returns -1 in case the thread was running and has been killed. Returns
415/// 0 in case the thread has been Delete and Cleaned up. The th pointer is
416/// not valid anymore in that case.
417
419{
420 if (!th) return 0;
421 th->fHolder = &th;
422
423 if (th->fState == kRunningState) { // Cancel if running
425
426 if (gDebug)
427 th->Info("TThread::Delete", "deleting thread");
428
429 th->Kill();
430 return -1;
431 }
432
433 CleanUp();
434 return 0;
435}
436
437////////////////////////////////////////////////////////////////////////////////
438/// Static method to check if threads exist.
439/// Returns the number of running threads.
440
442{
444
445 Int_t num = 0;
446 for (TThread *l = fgMain; l; l = l->fNext)
447 num++; //count threads
448
450
451 return num;
452}
453
454////////////////////////////////////////////////////////////////////////////////
455/// Set thread priority.
456
461
462////////////////////////////////////////////////////////////////////////////////
463/// Static method to find a thread by id.
464
466{
467 TThread *myTh;
468
470
471 for (myTh = fgMain; myTh && (myTh->fId != id); myTh = myTh->fNext) { }
472
474
475 return myTh;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// Static method to find a thread by name.
480
482{
483 TThread *myTh;
484
486
487 for (myTh = fgMain; myTh && (strcmp(name, myTh->GetName())); myTh = myTh->fNext) { }
488
490
491 return myTh;
492}
493
494////////////////////////////////////////////////////////////////////////////////
495/// Static method returning pointer to current thread.
496
498{
499 TTHREAD_TLS(TThread *) self = nullptr;
500
501 if (!self || fgIsTearDown) {
502 if (fgIsTearDown)
503 self = nullptr;
504 self = GetThread(SelfId());
505 }
506 return self;
507}
508
509
510////////////////////////////////////////////////////////////////////////////////
511/// Join this thread.
512
514{
515 if (fId == -1) {
516 Error("Join", "thread not running");
517 return -1;
518 }
519
520 if (fDetached) {
521 Error("Join", "cannot join detached thread");
522 return -1;
523 }
524
525 if (SelfId() != fgMainId)
526 return fgThreadImp->Join(this, ret);
527
528 // do not block the main thread, use helper thread
529 TJoinHelper helper(this, ret);
530
531 return helper.Join();
532}
533
534////////////////////////////////////////////////////////////////////////////////
535/// Static method to join a thread by id.
536
538{
540
541 if (!myTh) {
542 ::Error("TThread::Join", "cannot find thread 0x%lx", jid);
543 return -1L;
544 }
545
546 return myTh->Join(ret);
547}
548
549////////////////////////////////////////////////////////////////////////////////
550/// Static method returning the id for the current thread.
551
553{
554 if (fgIsTearDown) return -1;
555 if (!fgThreadImp) Init();
556
557 return fgThreadImp->SelfId();
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// Start the thread. This starts the static method TThread::Function()
562/// which calls the user function specified in the TThread ctor with
563/// the arg argument.
564/// If affinity is specified (>=0), a CPU affinity will be associated
565/// with the current thread.
566/// Returns 0 on success, otherwise an error number will
567/// be returned.
568
569Int_t TThread::Run(void *arg, const int affinity)
570{
571 if (arg) fThreadArg = arg;
572
573 SetComment("Run: MainInternalMutex locking");
575 SetComment("Run: MainMutex locked");
576
577 int iret = fgThreadImp->Run(this, affinity);
578
580
581 if (gDebug)
582 Info("TThread::Run", "thread run requested");
583
585 SetComment();
586 return iret;
587}
588
589////////////////////////////////////////////////////////////////////////////////
590/// Kill this thread. Returns 0 on success, otherwise an error number will
591/// be returned.
592
594{
596 if (gDebug)
597 Warning("TThread::Kill", "thread is not running");
598 return 13;
599 } else {
601 return fgThreadImp->Kill(this);
602 }
603}
604
605////////////////////////////////////////////////////////////////////////////////
606/// Static method to kill the thread by id. Returns 0 on success, otherwise
607/// an error number will be returned.
608
610{
611 TThread *th = GetThread(id);
612 if (th) {
613 return fgThreadImp->Kill(th);
614 } else {
615 if (gDebug)
616 ::Warning("TThread::Kill(Long_t)", "thread 0x%lx not found", id);
617 return 13;
618 }
619}
620
621////////////////////////////////////////////////////////////////////////////////
622/// Static method to kill thread by name. Returns 0 on success, otherwise
623/// an error number will be returned.
624
626{
627 TThread *th = GetThread(name);
628 if (th) {
629 return fgThreadImp->Kill(th);
630 } else {
631 if (gDebug)
632 ::Warning("TThread::Kill(const char*)", "thread %s not found", name);
633 return 13;
634 }
635}
636
637////////////////////////////////////////////////////////////////////////////////
638/// Static method to turn off thread cancellation. Returns 0 on success,
639/// otherwise an error number will be returned.
640
642{
643 return fgThreadImp ? fgThreadImp->SetCancelOff() : -1;
644}
645
646////////////////////////////////////////////////////////////////////////////////
647/// Static method to turn on thread cancellation. Returns 0 on success,
648/// otherwise an error number will be returned.
649
651{
652 return fgThreadImp ? fgThreadImp->SetCancelOn() : -1;
653}
654
655////////////////////////////////////////////////////////////////////////////////
656/// Static method to set the cancellation response type of the calling thread
657/// to asynchronous, i.e. cancel as soon as the cancellation request
658/// is received.
659
661{
662 return fgThreadImp ? fgThreadImp->SetCancelAsynchronous() : -1;
663}
664
665////////////////////////////////////////////////////////////////////////////////
666/// Static method to set the cancellation response type of the calling thread
667/// to deferred, i.e. cancel only at next cancellation point.
668/// Returns 0 on success, otherwise an error number will be returned.
669
671{
672 return fgThreadImp ? fgThreadImp->SetCancelDeferred() : -1;
673}
674
675////////////////////////////////////////////////////////////////////////////////
676/// Static method to set a cancellation point. Returns 0 on success, otherwise
677/// an error number will be returned.
678
680{
681 return fgThreadImp ? fgThreadImp->CancelPoint() : -1;
682}
683
684////////////////////////////////////////////////////////////////////////////////
685/// Static method which pushes thread cleanup method on stack.
686/// Returns 0 in case of success and -1 in case of error.
687
688Int_t TThread::CleanUpPush(void *free, void *arg)
689{
690 TThread *th = Self();
691 if (th)
692 return fgThreadImp->CleanUpPush(&(th->fClean), free, arg);
693 return -1;
694}
695
696////////////////////////////////////////////////////////////////////////////////
697/// Static method which pops thread cleanup method off stack.
698/// Returns 0 in case of success and -1 in case of error.
699
701{
702 TThread *th = Self();
703 if (th)
704 return fgThreadImp->CleanUpPop(&(th->fClean), exe);
705 return -1;
706}
707
708////////////////////////////////////////////////////////////////////////////////
709/// Static method to cleanup the calling thread.
710
712{
713 TThread *th = Self();
714 if (!th) return 13;
715
716 fgThreadImp->CleanUp(&(th->fClean));
717 fgMainMutex->CleanUp();
718 if (fgXActMutex)
719 fgXActMutex->CleanUp();
720
721 gMainInternalMutex->CleanUp();
722
723 if (th->fHolder)
724 delete th;
725
726 return 0;
727}
728
729////////////////////////////////////////////////////////////////////////////////
730/// Static method which is called after the thread has been canceled.
731
733{
734 if (th) {
736 if (gDebug)
737 th->Info("TThread::AfterCancel", "thread is canceled");
738 } else
739 ::Error("TThread::AfterCancel", "zero thread pointer passed");
740}
741
742////////////////////////////////////////////////////////////////////////////////
743/// Static method which terminates the execution of the calling thread.
744
746{
747 return fgThreadImp ? fgThreadImp->Exit(ret) : -1;
748}
749
750////////////////////////////////////////////////////////////////////////////////
751/// Static method to sleep the calling thread.
752
754{
755 UInt_t ms = UInt_t(secs * 1000) + UInt_t(nanos / 1000000);
756 if (gSystem) gSystem->Sleep(ms);
757 return 0;
758}
759
760////////////////////////////////////////////////////////////////////////////////
761/// Static method to get the current time. Returns
762/// the number of seconds.
763
765{
766 TTimeStamp t;
767 if (absSec) *absSec = t.GetSec();
768 if (absNanoSec) *absNanoSec = t.GetNanoSec();
769 return t.GetSec();
770}
771
772////////////////////////////////////////////////////////////////////////////////
773/// Static method to lock the main thread mutex.
774
776{
777 return (fgMainMutex ? fgMainMutex->Lock() : 0);
778}
779
780////////////////////////////////////////////////////////////////////////////////
781/// Static method to try to lock the main thread mutex.
782
784{
785 return (fgMainMutex ? fgMainMutex->TryLock() : 0);
786}
787
788////////////////////////////////////////////////////////////////////////////////
789/// Static method to unlock the main thread mutex.
790
792{
793 return (fgMainMutex ? fgMainMutex->UnLock() : 0);
794}
795
796////////////////////////////////////////////////////////////////////////////////
797/// Static method which is called by the system thread function and
798/// which in turn calls the actual user function.
799
800void *TThread::Function(void *ptr)
801{
802 TThread *th;
803 void *ret, *arg;
804
805 TThreadCleaner dummy;
806
807 th = (TThread *)ptr;
808
809 // Default cancel state is OFF
810 // Default cancel type is DEFERRED
811 // User can change it by call SetCancelOn() and SetCancelAsynchronous()
812 SetCancelOff();
814 CleanUpPush((void *)&AfterCancel, th); // Enable standard cancelling function
815
816 if (gDebug)
817 th->Info("TThread::Function", "thread is running");
818
819 arg = th->fThreadArg;
820 th->fState = kRunningState;
821
822 if (th->fDetached) {
823 //Detached, non joinable thread
824 (th->fFcnVoid)(arg);
825 ret = nullptr;
827 } else {
828 //UnDetached, joinable thread
829 ret = (th->fFcnRetn)(arg);
831 }
832
833 CleanUpPop(1); // Disable standard canceling function
834
835 if (gDebug)
836 th->Info("TThread::Function", "thread has finished");
837
839
840 return ret;
841}
842
843////////////////////////////////////////////////////////////////////////////////
844/// Static method listing the existing threads.
845
847{
848 TThread *l;
849 int i;
850
851 if (!fgMain) {
852 ::Info("TThread::Ps", "no threads have been created");
853 return;
854 }
855
857
858 int num = 0;
859 for (l = fgMain; l; l = l->fNext)
860 num++;
861
862 char cbuf[256];
863 printf(" Thread State\n");
864 for (l = fgMain; l; l = l->fNext) { // loop over threads
865 memset(cbuf, ' ', sizeof(cbuf));
866 snprintf(cbuf, sizeof(cbuf), "%3d %s:0x%lx", num--, l->GetName(), l->fId);
867 i = (int)strlen(cbuf);
868 if (i < 30)
869 cbuf[i] = ' ';
870 cbuf[30] = 0;
871 printf("%30s", cbuf);
872
873 switch (l->fState) { // print states
874 case kNewState: printf("Idle "); break;
875 case kRunningState: printf("Running "); break;
876 case kTerminatedState: printf("Terminated "); break;
877 case kFinishedState: printf("Finished "); break;
878 case kCancelingState: printf("Canceling "); break;
879 case kCanceledState: printf("Canceled "); break;
880 case kDeletingState: printf("Deleting "); break;
881 default: printf("Invalid ");
882 }
883 if (l->fComment[0]) printf(" // %s", l->fComment);
884 printf("\n");
885 } // end of loop
886
888}
889
890////////////////////////////////////////////////////////////////////////////////
891/// Static method returning a pointer to thread specific data container
892/// of the calling thread.
893/// k should be between 0 and kMaxUserThreadSlot for user application.
894/// (and between kMaxUserThreadSlot and kMaxThreadSlot for ROOT libraries).
895/// See ROOT::EThreadSlotReservation
896
897void **TThread::Tsd(void *dflt, Int_t k)
898{
899 if (TThread::SelfId() == fgMainId) { //Main thread
900 return (void**)dflt;
901 } else {
902 return GetTls(k);
903 }
904}
905
906////////////////////////////////////////////////////////////////////////////////
907/// Static method that initializes the TLS array of a thread and returns the
908/// reference to a given position in that array.
909
912
913 return &(tls[k]);
914}
915
916////////////////////////////////////////////////////////////////////////////////
917/// Static method providing a thread safe printf. Appends a newline.
918
919void TThread::Printf(const char *va_(fmt), ...)
920{
921 va_list ap;
922 va_start(ap,va_(fmt));
923
924 Int_t buf_size = 2048;
925 char *buf;
926
927again:
928 buf = new char[buf_size];
929
930 int n = vsnprintf(buf, buf_size, va_(fmt), ap);
931 // old vsnprintf's return -1 if string is truncated new ones return
932 // total number of characters that would have been written
933 if (n == -1 || n >= buf_size) {
934 buf_size *= 2;
935 delete [] buf;
936 goto again;
937 }
938
939 va_end(ap);
940
941 void *arr[2];
942 arr[1] = (void*) buf;
943 if (XARequest("PRTF", 2, arr, nullptr)) {
944 delete [] buf;
945 return;
946 }
947
948 printf("%s\n", buf);
949 fflush(stdout);
950
951 delete [] buf;
952}
953
954////////////////////////////////////////////////////////////////////////////////
955/// Thread specific error handler function.
956/// It calls the user set error handler in the main thread.
957
958void TThread::ErrorHandler(int level, const char *location, const char *fmt,
959 va_list ap) const
960{
961 Int_t buf_size = 2048;
962 char *buf, *bp;
963
964again:
965 buf = new char[buf_size];
966
967 int n = vsnprintf(buf, buf_size, fmt, ap);
968 // old vsnprintf's return -1 if string is truncated new ones return
969 // total number of characters that would have been written
970 if (n == -1 || n >= buf_size) {
971 buf_size *= 2;
972 delete [] buf;
973 goto again;
974 }
975 if (level >= kSysError && level < kFatal) {
976 const std::size_t bufferSize = buf_size + strlen(gSystem->GetError()) + 5;
977 char *buf1 = new char[bufferSize];
978 snprintf(buf1, bufferSize, "%s (%s)", buf, gSystem->GetError());
979 bp = buf1;
980 delete [] buf;
981 } else
982 bp = buf;
983
984 void *arr[4];
985 arr[1] = (void*) Longptr_t(level);
986 arr[2] = (void*) location;
987 arr[3] = (void*) bp;
988 if (XARequest("ERRO", 4, arr, nullptr))
989 return;
990
991 if (level != kFatal)
992 ::GetErrorHandler()(level, level >= gErrorAbortLevel, location, bp);
993 else
994 ::GetErrorHandler()(level, kTRUE, location, bp);
995
996 delete [] bp;
997}
998
999////////////////////////////////////////////////////////////////////////////////
1000/// Interface to ErrorHandler. User has to specify the class name as
1001/// part of the location, just like for the global Info(), Warning() and
1002/// Error() functions.
1003
1004void TThread::DoError(int level, const char *location, const char *fmt,
1005 va_list va) const
1006{
1007 char *loc = nullptr;
1008
1009 if (location) {
1010 const std::size_t bufferSize = strlen(location) + strlen(GetName()) + 32;
1011 loc = new char[bufferSize];
1012 snprintf(loc, bufferSize, "%s %s:0x%lx", location, GetName(), fId);
1013 } else {
1014 const std::size_t bufferSize = strlen(GetName()) + 32;
1015 loc = new char[bufferSize];
1016 snprintf(loc, bufferSize, "%s:0x%lx", GetName(), fId);
1017 }
1018
1019 ErrorHandler(level, loc, fmt, va);
1020
1021 delete [] loc;
1022}
1023
1024////////////////////////////////////////////////////////////////////////////////
1025/// Static method used to allow commands to be executed by the main thread.
1026
1028{
1029 if (!gApplication || !gApplication->IsRunning()) return 0;
1030
1031 // The first time, create the related static vars
1032 if (!fgXActMutex && gGlobalMutex) {
1033 gGlobalMutex->Lock();
1034 if (!fgXActMutex) {
1035 fgXActMutex = new TMutex(kTRUE);
1036 fgXActCondi = new TCondition;
1037 new TThreadTimer;
1038 }
1040 }
1041
1042 TThread *th = Self();
1043 if (th && th->fId != fgMainId) { // we are in the thread
1044 th->SetComment("XARequest: XActMutex Locking");
1045 fgXActMutex->Lock();
1046 th->SetComment("XARequest: XActMutex Locked");
1047
1048 TConditionImp *condimp = fgXActCondi->fConditionImp;
1049 TMutexImp *condmutex = fgXActCondi->GetMutex()->fMutexImp;
1050
1051 // Lock now, so the XAction signal will wait
1052 // and never come before the wait
1053 condmutex->Lock();
1054
1055 fgXAnb = nb;
1056 fgXArr = ar;
1057 fgXArt = 0;
1058 fgXAct = (char*) xact;
1059 th->SetComment(fgXAct);
1060
1061 if (condimp) condimp->Wait();
1062 condmutex->UnLock();
1063
1064 if (iret) *iret = fgXArt;
1065 fgXActMutex->UnLock();
1066 th->SetComment();
1067 return 1997;
1068 } else //we are in the main thread
1069 return 0;
1070}
1071
1072////////////////////////////////////////////////////////////////////////////////
1073/// Static method called via the thread timer to execute in the main
1074/// thread certain commands. This to avoid sophisticated locking and
1075/// possible deadlocking.
1076
1078{
1079 TConditionImp *condimp = fgXActCondi->fConditionImp;
1080 TMutexImp *condmutex = fgXActCondi->GetMutex()->fMutexImp;
1081 condmutex->Lock();
1082
1083 char const acts[] = "PRTF CUPD CANV CDEL PDCD METH ERRO";
1084 enum { kPRTF = 0, kCUPD = 5, kCANV = 10, kCDEL = 15,
1085 kPDCD = 20, kMETH = 25, kERRO = 30 };
1086 int iact = strstr(acts, fgXAct) - acts;
1087 TString cmd;
1088
1089 switch (iact) {
1090
1091 case kPRTF:
1092 printf("%s\n", (const char*)fgXArr[1]);
1093 fflush(stdout);
1094 break;
1095
1096 case kERRO:
1097 {
1098 int level = (int)Longptr_t(fgXArr[1]);
1099 const char *location = (const char*)fgXArr[2];
1100 char *mess = (char*)fgXArr[3];
1101 if (level != kFatal)
1102 GetErrorHandler()(level, level >= gErrorAbortLevel, location, mess);
1103 else
1104 GetErrorHandler()(level, kTRUE, location, mess);
1105 delete [] mess;
1106 }
1107 break;
1108
1109 case kCUPD:
1110 //((TCanvas *)fgXArr[1])->Update();
1112 void (*fFuncPtr)(void*);
1113 void* fVoidPtr;
1115 castFromFuncToVoidPtr.fVoidPtr = fgXArr[2];
1116 (*castFromFuncToVoidPtr.fFuncPtr)(fgXArr[1]); // aka TCanvas::Update()
1117 break;
1118
1119 case kCANV:
1120
1121 switch(fgXAnb) { // Over TCanvas constructors
1122
1123 case 2:
1124 //((TCanvas*)fgXArr[1])->Constructor();
1125 cmd.Form("((TCanvas *)0x%zx)->Constructor();",(size_t)fgXArr[1]);
1126 gROOT->ProcessLine(cmd.Data());
1127 break;
1128
1129 case 5:
1130 //((TCanvas*)fgXArr[1])->Constructor(
1131 // (char*)fgXArr[2],
1132 // (char*)fgXArr[3],
1133 // *((Int_t*)(fgXArr[4])));
1134 cmd.Form("((TCanvas *)0x%zx)->Constructor((char*)0x%zx,(char*)0x%zx,*((Int_t*)(0x%zx)));",(size_t)fgXArr[1],(size_t)fgXArr[2],(size_t)fgXArr[3],(size_t)fgXArr[4]);
1135 gROOT->ProcessLine(cmd.Data());
1136 break;
1137 case 6:
1138 //((TCanvas*)fgXArr[1])->Constructor(
1139 // (char*)fgXArr[2],
1140 // (char*)fgXArr[3],
1141 // *((Int_t*)(fgXArr[4])),
1142 // *((Int_t*)(fgXArr[5])));
1143 cmd.Form("((TCanvas *)0x%zx)->Constructor((char*)0x%zx,(char*)0x%zx,*((Int_t*)(0x%zx)),*((Int_t*)(0x%zx)));",(size_t)fgXArr[1],(size_t)fgXArr[2],(size_t)fgXArr[3],(size_t)fgXArr[4],(size_t)fgXArr[5]);
1144 gROOT->ProcessLine(cmd.Data());
1145 break;
1146
1147 case 8:
1148 //((TCanvas*)fgXArr[1])->Constructor(
1149 // (char*)fgXArr[2],
1150 // (char*)fgXArr[3],
1151 // *((Int_t*)(fgXArr[4])),
1152 // *((Int_t*)(fgXArr[5])),
1153 // *((Int_t*)(fgXArr[6])),
1154 // *((Int_t*)(fgXArr[7])));
1155 cmd.Form("((TCanvas *)0x%zx)->Constructor((char*)0x%zx,(char*)0x%zx,*((Int_t*)(0x%zx)),*((Int_t*)(0x%zx)),*((Int_t*)(0x%zx)),*((Int_t*)(0x%zx)));",(size_t)fgXArr[1],(size_t)fgXArr[2],(size_t)fgXArr[3],(size_t)fgXArr[4],(size_t)fgXArr[5],(size_t)fgXArr[6],(size_t)fgXArr[7]);
1156 gROOT->ProcessLine(cmd.Data());
1157 break;
1158
1159 }
1160 break;
1161
1162 case kCDEL:
1163 //((TCanvas*)fgXArr[1])->Destructor();
1164 cmd.Form("((TCanvas *)0x%zx)->Destructor();",(size_t)fgXArr[1]);
1165 gROOT->ProcessLine(cmd.Data());
1166 break;
1167
1168 case kPDCD:
1169 ((TVirtualPad*) fgXArr[1])->Divide( *((Int_t*)(fgXArr[2])),
1170 *((Int_t*)(fgXArr[3])),
1171 *((Float_t*)(fgXArr[4])),
1172 *((Float_t*)(fgXArr[5])),
1173 *((Int_t*)(fgXArr[6])));
1174 break;
1175 case kMETH:
1176 ((TMethodCall *) fgXArr[1])->Execute((void*)(fgXArr[2]),(const char*)(fgXArr[3]));
1177 break;
1178
1179 default:
1180 ::Error("TThread::XAction", "wrong case");
1181 }
1182
1183 fgXAct = nullptr;
1184 if (condimp) condimp->Signal();
1185 condmutex->UnLock();
1186}
1187
1188
1189//////////////////////////////////////////////////////////////////////////
1190// //
1191// TThreadTimer //
1192// //
1193//////////////////////////////////////////////////////////////////////////
1194
1195////////////////////////////////////////////////////////////////////////////////
1196/// Create thread timer.
1197
1199{
1200 gSystem->AddTimer(this);
1201}
1202
1203////////////////////////////////////////////////////////////////////////////////
1204/// Periodically execute the TThread::XAction() method in the main thread.
1205
1207{
1209 Reset();
1210
1211 return kFALSE;
1212}
1213
1214
1215//////////////////////////////////////////////////////////////////////////
1216// //
1217// TThreadCleaner //
1218// //
1219//////////////////////////////////////////////////////////////////////////
1220
1221////////////////////////////////////////////////////////////////////////////////
1222/// Call user clean up routines.
1223
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
R__EXTERN TApplication * gApplication
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Int_t gErrorAbortLevel
non-ignored errors with level equal or above this value will call abort(). Default is kSysError+1.
Definition TError.cxx:34
ErrorHandlerFunc_t GetErrorHandler()
Returns the current error handler function.
Definition TError.cxx:102
constexpr Int_t kFatal
Definition TError.h:50
constexpr Int_t kSysError
Definition TError.h:49
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
R__EXTERN TInterpreter * gCling
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:411
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
R__EXTERN TThreadFactory * gThreadFactory
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
static TMutex * gMainInternalMutex
Definition TThread.cxx:58
static void ThreadInternalUnLock()
Definition TThread.cxx:61
static void CINT_alloc_lock()
Definition TThread.cxx:55
static TThreadTearDownGuard gTearDownGuard
Definition TThread.cxx:91
static Bool_t fgIsTearDown(kFALSE)
static void ThreadInternalLock()
Definition TThread.cxx:60
void ROOT_TThread_Initialize()
Definition TThread.cxx:65
static void CINT_alloc_unlock()
Definition TThread.cxx:56
R__EXTERN TVirtualMutex * gGlobalMutex
#define R__LOCKGUARD(mutex)
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
#define va_(arg)
Definition Varargs.h:35
#define snprintf
Definition civetweb.c:1579
Bool_t IsRunning() const
Int_t TimedWaitRelative(ULong_t ms)
Wait to be signaled or till the timer times out.
virtual void SetAllocunlockfunc(void(*)()) const
static TInterpreter * Instance()
returns gInterpreter global
TJoinHelper(TThread *th, void **ret)
Constructor of Thread helper class.
Definition TThread.cxx:117
TMutex * fM
Definition TThread.cxx:101
Int_t Join()
Thread join function.
Definition TThread.cxx:157
Bool_t fJoined
Definition TThread.cxx:103
Long_t fRc
Definition TThread.cxx:100
TThread * fH
Definition TThread.cxx:98
void ** fRet
Definition TThread.cxx:99
~TJoinHelper()
Destructor.
Definition TThread.cxx:126
TCondition * fC
Definition TThread.cxx:102
static void * JoinFunc(void *p)
Static method which runs in a separate thread to handle thread joins without blocking the main thread...
Definition TThread.cxx:138
TThread * fT
Definition TThread.cxx:97
Method or function calling interface.
Definition TMethodCall.h:37
Int_t UnLock() override
Unlock the mutex.
Definition TMutex.cxx:67
Int_t Lock() override
Lock the mutex.
Definition TMutex.cxx:45
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:457
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
Basic string class.
Definition TString.h:138
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition TSystem.cxx:469
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:435
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:414
virtual const char * GetError()
Return system error string.
Definition TSystem.cxx:252
~TThreadCleaner()
Call user clean up routines.
Definition TThread.cxx:1224
virtual TThreadImp * CreateThreadImp()=0
Bool_t Notify() override
Periodically execute the TThread::XAction() method in the main thread.
Definition TThread.cxx:1206
TThreadTimer(Long_t ms=kItimerResolution+10)
Create thread timer.
Definition TThread.cxx:1198
<div class="legacybox"><h2>Legacy Code</h2> TThread is a legacy interface: there will be no bug fixes...
Definition TThread.h:40
VoidRtnFunc_t fFcnRetn
Definition TThread.h:84
static TThread * GetThread(Long_t id)
Static method to find a thread by id.
Definition TThread.cxx:465
static Int_t CleanUpPop(Int_t exe=0)
Static method which pops thread cleanup method off stack.
Definition TThread.cxx:700
static Int_t CancelPoint()
Static method to set a cancellation point.
Definition TThread.cxx:679
static Int_t Sleep(ULong_t secs, ULong_t nanos=0)
Static method to sleep the calling thread.
Definition TThread.cxx:753
static void **volatile fgXArr
Definition TThread.h:92
static Int_t CleanUpPush(void *free, void *arg=nullptr)
Static method which pushes thread cleanup method on stack.
Definition TThread.cxx:688
static Int_t TryLock()
Static method to try to lock the main thread mutex.
Definition TThread.cxx:783
void SetPriority(EPriority pri)
Set thread priority.
Definition TThread.cxx:457
static Int_t Exists()
Static method to check if threads exist.
Definition TThread.cxx:441
TThread * fPrev
Definition TThread.h:75
static void Ps()
Static method listing the existing threads.
Definition TThread.cxx:846
static void ** GetTls(Int_t k)
Static method that initializes the TLS array of a thread and returns the reference to a given positio...
Definition TThread.cxx:910
static TThreadImp * fgThreadImp
Definition TThread.h:90
static Int_t UnLock()
Static method to unlock the main thread mutex.
Definition TThread.cxx:791
Int_t Kill()
Kill this thread.
Definition TThread.cxx:593
static TMutex * fgMainMutex
Definition TThread.h:97
EState fState
Definition TThread.h:78
static volatile Int_t fgXAnb
Definition TThread.h:93
static Long_t fgMainId
Definition TThread.h:95
Long_t Join(void **ret=nullptr)
Join this thread.
Definition TThread.cxx:513
static void XAction()
Static method called via the thread timer to execute in the main thread certain commands.
Definition TThread.cxx:1077
virtual ~TThread()
Cleanup the thread.
Definition TThread.cxx:391
Bool_t fDetached
Definition TThread.h:82
static Int_t SetCancelAsynchronous()
Static method to set the cancellation response type of the calling thread to asynchronous,...
Definition TThread.cxx:660
static Int_t CleanUp()
Static method to cleanup the calling thread.
Definition TThread.cxx:711
void ErrorHandler(int level, const char *location, const char *fmt, va_list ap) const
Thread specific error handler function.
Definition TThread.cxx:958
static Int_t GetTime(ULong_t *absSec, ULong_t *absNanoSec)
Static method to get the current time.
Definition TThread.cxx:764
static Long_t SelfId()
Static method returning the id for the current thread.
Definition TThread.cxx:552
void Constructor()
Common thread constructor.
Definition TThread.cxx:363
static Int_t SetCancelOn()
Static method to turn on thread cancellation.
Definition TThread.cxx:650
static void ** Tsd(void *dflt, Int_t k)
Static method returning a pointer to thread specific data container of the calling thread.
Definition TThread.cxx:897
Long_t fId
Definition TThread.h:80
Bool_t fNamed
Definition TThread.h:83
Int_t Run(void *arg=nullptr, const int affinity=-1)
Start the thread.
Definition TThread.cxx:569
static volatile Int_t fgXArt
Definition TThread.h:94
void SetComment(const char *txt=nullptr)
Definition TThread.h:103
void DoError(Int_t level, const char *location, const char *fmt, va_list va) const override
Interface to ErrorHandler.
Definition TThread.cxx:1004
static Int_t XARequest(const char *xact, Int_t nb, void **ar, Int_t *iret)
Static method used to allow commands to be executed by the main thread.
Definition TThread.cxx:1027
static std::atomic< char * > volatile fgXAct
Definition TThread.h:48
VoidFunc_t fFcnVoid
Definition TThread.h:85
static void * Function(void *ptr)
Static method which is called by the system thread function and which in turn calls the actual user f...
Definition TThread.cxx:800
EPriority fPriority
Definition TThread.h:77
static void Printf(const char *fmt,...)
Static method providing a thread safe printf. Appends a newline.
Definition TThread.cxx:919
static Int_t Lock()
Static method to lock the main thread mutex.
Definition TThread.cxx:775
@ kRunningState
Definition TThread.h:64
@ kNewState
Definition TThread.h:63
@ kCanceledState
Definition TThread.h:69
@ kCancelingState
Definition TThread.h:68
@ kFinishedState
Definition TThread.h:67
@ kTerminatedState
Definition TThread.h:65
@ kDeletingState
Definition TThread.h:70
@ kInvalidState
Definition TThread.h:62
friend class TThreadTimer
Definition TThread.h:44
static Int_t SetCancelOff()
Static method to turn off thread cancellation.
Definition TThread.cxx:641
static void Init()
Initialize global state and variables once.
Definition TThread.cxx:318
static Int_t SetCancelDeferred()
Static method to set the cancellation response type of the calling thread to deferred,...
Definition TThread.cxx:670
Longptr_t fHandle
Definition TThread.h:81
static void AfterCancel(TThread *th)
Static method which is called after the thread has been canceled.
Definition TThread.cxx:732
static TThread * fgMain
Definition TThread.h:96
static TMutex * fgXActMutex
Definition TThread.h:98
EPriority
Definition TThread.h:55
@ kNormalPriority
Definition TThread.h:57
static Bool_t IsInitialized()
Return true, if the TThread objects have been initialize.
Definition TThread.cxx:308
static TThread * Self()
Static method returning pointer to current thread.
Definition TThread.cxx:497
static Int_t Exit(void *ret=nullptr)
Static method which terminates the execution of the calling thread.
Definition TThread.cxx:745
static void Initialize()
Initialize the Thread package.
Definition TThread.cxx:299
void * fClean
Definition TThread.h:87
static TCondition * fgXActCondi
Definition TThread.h:99
TThread(const TThread &)=delete
TThread ** fHolder
Definition TThread.h:76
TThread * fNext
Definition TThread.h:74
void Delete(Option_t *option="") override
Delete this object.
Definition TThread.h:127
void * fThreadArg
Definition TThread.h:86
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
time_t GetSec() const
Definition TTimeStamp.h:109
Int_t GetNanoSec() const
Definition TTimeStamp.h:110
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
void Reset()
Reset the timer.
Definition TTimer.cxx:162
This class implements a mutex interface.
virtual Int_t UnLock()=0
virtual Int_t Lock()=0
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
const Int_t n
Definition legend1.C:16
R__EXTERN TVirtualRWMutex * gCoreMutex
@ kMaxThreadSlot
TROOT * GetROOT()
Definition TROOT.cxx:477
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4