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