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