// @(#)root/thread:$Id$ // Author: Fons Rademakers 02/07/97 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #ifndef ROOT_TThread #define ROOT_TThread ////////////////////////////////////////////////////////////////////////// // // // TThread // // // // This class implements threads. A thread is an execution environment // // much lighter than a process. A single process can have multiple // // threads. The actual work is done via the TThreadImp class (either // // TPosixThread or TWin32Thread). // // // ////////////////////////////////////////////////////////////////////////// #include "TNamed.h" #include "TTimer.h" #include #ifdef R__LESS_INCLUDES class TCondition; #else #include "TCondition.h" #endif class TMutex; class TThreadImp; class TThread : public TNamed { friend class TThreadImp; friend class TPosixThread; friend class TThreadTimer; friend class TThreadCleaner; friend class TWin32Thread; friend class TThreadTearDownGuard; friend class TJoinHelper; public: typedef void *(*VoidRtnFunc_t)(void *); typedef void (*VoidFunc_t)(void *); enum EPriority { kLowPriority, kNormalPriority, kHighPriority }; enum EState { kInvalidState, // thread was not created properly kNewState, // thread object exists but hasn't started kRunningState, // thread is running kTerminatedState, // thread has terminated but storage has not // yet been reclaimed (i.e. waiting to be joined) kFinishedState, // thread has finished kCancelingState, // thread in process of canceling kCanceledState, // thread has been canceled kDeletingState // thread in process of deleting }; private: TThread *fNext; // pointer to next thread TThread *fPrev; // pointer to prev thread TThread **fHolder; // pointer to holder of this (delete only) EPriority fPriority; // thread priority EState fState; // thread state EState fStateComing; // coming thread state Long_t fId; // thread id Longptr_t fHandle; // Win32 thread handle Bool_t fDetached; // kTRUE if thread is Detached Bool_t fNamed; // kTRUE if thread is Named VoidRtnFunc_t fFcnRetn; // void* start function of thread VoidFunc_t fFcnVoid; // void start function of thread void *fThreadArg; // thread start function arguments void *fClean; // support of cleanup structure char fComment[100]; // thread specific state comment static TThreadImp *fgThreadImp; // static pointer to thread implementation static std::atomic volatile fgXAct; // Action name to do by main thread static void ** volatile fgXArr; // pointer to control array of void pointers for action static volatile Int_t fgXAnb; // size of array above static volatile Int_t fgXArt; // return XA flag static Long_t fgMainId; // thread id of main thread static TThread *fgMain; // pointer to chain of TThread's static TMutex *fgMainMutex; // mutex to protect chain of threads static TMutex *fgXActMutex; // mutex to protect XAction static TCondition *fgXActCondi; // condition for XAction // Private Member functions void Constructor(); void SetComment(const char *txt = nullptr) { fComment[0] = 0; if (txt) { strncpy(fComment, txt, 99); fComment[99] = 0; } } void DoError(Int_t level, const char *location, const char *fmt, va_list va) const override; void ErrorHandler(int level, const char *location, const char *fmt, va_list ap) const; static void Init(); static void *Function(void *ptr); static Int_t XARequest(const char *xact, Int_t nb, void **ar, Int_t *iret); static void AfterCancel(TThread *th); static void **GetTls(Int_t k); TThread(const TThread&) = delete; TThread& operator=(const TThread&) = delete; public: TThread(VoidRtnFunc_t fn, void *arg = nullptr, EPriority pri = kNormalPriority); TThread(VoidFunc_t fn, void *arg = nullptr, EPriority pri = kNormalPriority); TThread(const char *thname, VoidRtnFunc_t fn, void *arg = nullptr, EPriority pri = kNormalPriority); TThread(const char *thname, VoidFunc_t fn, void *arg = nullptr, EPriority pri = kNormalPriority); TThread(Long_t id = 0); virtual ~TThread(); Int_t Kill(); Int_t Run(void *arg = nullptr, const int affinity = -1); void SetPriority(EPriority pri); void Delete(Option_t *option="") override { TObject::Delete(option); } EPriority GetPriority() const { return fPriority; } EState GetState() const { return fState; } Long_t GetId() const { return fId; } static void Ps(); static void ps() { Ps(); } static void Initialize(); static Bool_t IsInitialized(); Long_t Join(void **ret = nullptr); static Long_t Join(Long_t id, void **ret = nullptr); static Int_t Exit(void *ret = nullptr); static Int_t Exists(); static TThread *GetThread(Long_t id); static TThread *GetThread(const char *name); static Int_t Lock(); //User's lock of main mutex static Int_t TryLock(); //User's try lock of main mutex static Int_t UnLock(); //User's unlock of main mutex static TThread *Self(); static Long_t SelfId(); static Int_t Sleep(ULong_t secs, ULong_t nanos = 0); static Int_t GetTime(ULong_t *absSec, ULong_t *absNanoSec); static Int_t Delete(TThread *&th); static void **Tsd(void *dflt, Int_t k); // Cancellation // there are two types of TThread cancellation: // DEFERRED - Cancellation only in user provided cancel-points // ASYNCHRONOUS - In any point // DEFERRED is more safe, it is DEFAULT. static Int_t SetCancelOn(); static Int_t SetCancelOff(); static Int_t SetCancelAsynchronous(); static Int_t SetCancelDeferred(); static Int_t CancelPoint(); static Int_t Kill(Long_t id); static Int_t Kill(const char *name); static Int_t CleanUpPush(void *free, void *arg = nullptr); static Int_t CleanUpPop(Int_t exe = 0); static Int_t CleanUp(); // XActions static void Printf(const char *fmt, ...) // format and print #if defined(__GNUC__) && !defined(__CINT__) __attribute__((format(printf, 1, 2))) #endif ; static void XAction(); ClassDefOverride(TThread,0) // Thread class }; ////////////////////////////////////////////////////////////////////////// // // // TThreadCleaner // // // ////////////////////////////////////////////////////////////////////////// class TThreadCleaner { public: TThreadCleaner() { } ~TThreadCleaner(); }; ////////////////////////////////////////////////////////////////////////// // // // TThreadTimer // // // ////////////////////////////////////////////////////////////////////////// class TThreadTimer : public TTimer { public: // if this time is less or equal to kItimerResolution, TUnixSystem::DispatchOneEvent i // can not exit and have its caller react to the other TTimer's actions (like the request // to stop the event loop) until there is another type of event. TThreadTimer(Long_t ms = kItimerResolution + 10); Bool_t Notify() override; }; #endif