GSI Object Oriented Online Offline (Go4) GO4-6.4.0
Loading...
Searching...
No Matches
TGo4Thread.cxx
Go to the documentation of this file.
1// $Id$
2//-----------------------------------------------------------------------
3// The GSI Online Offline Object Oriented (Go4) Project
4// Experiment Data Processing at EE department, GSI
5//-----------------------------------------------------------------------
6// Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7// Planckstr. 1, 64291 Darmstadt, Germany
8// Contact: http://go4.gsi.de
9//-----------------------------------------------------------------------
10// This software can be used under the license agreements as stated
11// in Go4License.txt file which is part of the distribution.
12//-----------------------------------------------------------------------
13
14#include "TGo4Thread.h"
15
16#include "TThread.h"
17#include "TSystem.h"
18#include "TCondition.h"
19
20#include "TGo4Runnable.h"
21#include "TGo4Log.h"
22#include "Go4Exceptions.h"
23
25 :TNamed(right)
26{
27 GO4TRACE((14,"TGo4Thread::TGo4Thread(const TGo4Thread &)",__LINE__, __FILE__));
28 fxRunnable = right.fxRunnable;
30 fxCondition = new TCondition();
31}
32
33TGo4Thread::TGo4Thread (const char *name, TGo4Runnable *runnable, Bool_t internal)
34 :TNamed(name,"This is a TGo4Thread"),
35 fbIsCreated(kFALSE),
36 fbIsRunning(kFALSE),
37 fiThreadPID(0),
39 fbIsWaiting(kFALSE),
40 fxThread(nullptr)
41{
42 GO4TRACE((14,"TGo4Thread::TGo4Thread(const char *, TGo4Runnable *, Bool_t)",__LINE__, __FILE__));
43
44 TGo4Log::Debug(" New Go4Thread ``%s'' created ",name);
45 fxRunnable = runnable;
46 fbIsInternal = internal;
47 fxCondition = new TCondition();
48 fxRunnable->SetThread(this);
49}
50
51
53{
54 GO4TRACE((14,"TGo4Thread::~TGo4Thread()",__LINE__, __FILE__));
55
56 Stop();
57 Cancel();
58 delete fxCondition;
59 fxCondition = nullptr;
60 if (fbIsInternal) {
61 GO4TRACE((14, "TGo4Thread::~TGo4Thread() internal mode", __LINE__, __FILE__));
62 TGo4Log::Debug(" Go4Thread ``%s'' deleting runnable ``%s'' ", GetName(), fxRunnable->GetName());
63 delete fxRunnable; // internal mode: go4thread responsible for runnable
64 } else {
65 GO4TRACE((14, "TGo4Thread::~TGo4Thread() non internal mode", __LINE__, __FILE__));
66 // do nothing
67 }
68}
69
71{
72 GO4TRACE((2,"TGo4Thread::Threadfunc(void *)",__LINE__, __FILE__));
73 TGo4Thread *go4th = (TGo4Thread *) arg; // we need reference to calling class instance
74 TGo4Runnable *runnable = go4th->GetRunnable();
75
76 // this is the function running as pthread...
77 // initializations:
78 go4th->SetPID();
79 go4th->SetSelfID();
80// fiThreadPID=gSystem->GetPid(); // set ids
81// fiThreadSelfID=TThread::SelfId();
82 TGo4Log::Debug(" TThread %ld (PID:%d) of Go4Thread ``%s'' started... \n",
83 go4th->GetSelfID(), go4th->GetPID(), go4th->GetName());
84
85for(;;) // loop keeps thread alive after exception has occurred...
86 {
87 try
88 {
89 GO4TRACE((1,"TGo4Thread::Threadfunc(void *) try block",__LINE__, __FILE__));
90 while(1)
91 {
92 TThread::CancelPoint();
93 if( !(go4th->IsRunning()) )
94 {
95 GO4TRACE((1,"TGo4Thread::Threadfunc(void *) waiting mode",__LINE__, __FILE__));
96 TGo4Log::Debug(" Go4Thread ``%s'' (PID:%d) waiting...\n",
97 go4th->GetName(), go4th->GetPID());
98 go4th->SetWaiting(kTRUE);
99 go4th->GetCondition()->Wait(); //wait for funcrun condition
100 go4th->SetWaiting(kFALSE);
101 TGo4Log::Debug(" Go4Thread ``%s'' (PID:%d) running...\n",
102 go4th->GetName(), go4th->GetPID() );
103 }
104 else
105 {
106 // Do Nothing, just continue
107 }
108
109 if(go4th->IsCreated())
110 // normal mode: enter runnable
111 {
112 GO4TRACE((1,"TGo4Thread::Threadfunc(void *) entering running mode",__LINE__, __FILE__));
113 // call runnable prerun method before running:
114 runnable->PreRun((void *) 0); // we are runnable's friend, can call protected method...
115 while(go4th->IsRunning())
116 {
117 TThread::CancelPoint();
118 runnable->Run((void *) 0); // we are runnable's friend, can call protected method...
119 }
120 // call runnable postrun method before stopping
121 runnable->PostRun((void *) 0); // we are runnable's friend, can call protected method...
122
123 }
124 else
125 // aborting mode after condition release: loop cancel point
126 {
127 GO4TRACE((1,"TGo4Thread::Threadfunc(void *) entering Cancel loop",__LINE__, __FILE__));
128 TGo4Log::Debug(" Go4Thread ``%s'' entering Cancel loop\n ", go4th->GetName());
129 while(!(go4th->IsCreated()))
130 {
131 {
132 #ifdef _MSC_VER
133 return; // cancel point does not work on windows; escape to root thread framework...
134 #else
135 GO4TRACE((1,"TGo4Thread::Threadfunc(void *) in Cancel loop",__LINE__, __FILE__));
136 Sleep(500);
137 TThread::CancelPoint();
138 #endif
139 }
140 }
141 }
142 } // while(1)
143 }// try
144 catch(TGo4Exception &ex)
145 {
146 GO4TRACE((1,"TGo4Thread::Threadfunc(void *) Go4Exception Catch",__LINE__, __FILE__));
147 runnable->ThreadCatch(ex);
148 TThread::CancelPoint();
149 }
150
151 catch(...)
152 {
153 GO4TRACE((1,"TGo4Thread::Threadfunc(void *) Unexpected Catch",__LINE__, __FILE__));
154 //runnable->UnexpectedCatch(); // do not handle alien exceptions!
155 TThread::CancelPoint();
156 throw; // otherwise, we have trouble with newer pthread
157 // implementations that use one pid for all threads, e.g. Fedora2
158 }
159
160 } // for(;;) loop keeps thread alive
161}
162
164{
165 GO4TRACE((14,"TGo4Thread::Create()",__LINE__, __FILE__));
166 // thread instance already there...
167 if(fbIsCreated)
168 return kFALSE;
169
170 fxThread= new TThread(GetName(),
171 (void(*) (void *)) &Threadfunc ,
172 (void *) this);
173 fxThread->Run();
174 fbIsCreated = kTRUE;
175 return kTRUE;
176}
177
179{
180 GO4TRACE((14,"TGo4Thread::Cancel()",__LINE__, __FILE__));
181
182 if(fbIsCreated) {
183 // thread existing, then cancel
184 TGo4Log::Debug(" Go4Thread ``%s'' -- Canceling TThread %ld (PID:%d) ",
185 GetName(), fiThreadSelfID, fiThreadPID);
186 if(fxThread) {
187 GO4TRACE((13,"TGo4Thread::Cancel() -- canceling existing TThread",__LINE__, __FILE__));
188 fbIsCreated = kFALSE;
189 fbIsRunning = kTRUE; // these settings let Threadfunc enter Cancel loop
190 fxCondition->Signal(); // unlock condition mutex before deleting it
191 Sleep(500); // waitstate for Threadfunc to enter cancel loop after condition
192
193 // JAM2018 bugfix for crashes with ROOT 6 concerning Thread CleanUpPop
194 TThread::Delete(fxThread);
195
196 fxThread = nullptr;
197 fiThreadPID = 0;
198 fiThreadSelfID = 0;
199 } else {
200 GO4TRACE((13,"TGo4Thread::Cancel() -- Error: TThread pointer is zero!",__LINE__, __FILE__));
201 TGo4Log::Debug(" Go4Thread ``%s'' Cancel -- Internal inconsistency error! ",GetName());
202 throw TGo4RuntimeException();
203 }
204 return kTRUE;
205 }
206 // no such thread...
207 return kFALSE;
208}
209
211{
212 GO4TRACE((14,"TGo4Thread::ReCreate()",__LINE__, __FILE__));
213
214 TThread* oldthread;
215 if(fbIsCreated)
216 // thread existing, then recreate possible
217
218 {
219 GO4TRACE((13,"TGo4Thread::ReCreate() -- old TThread existing",__LINE__, __FILE__));
220 TGo4Log::Debug(" Recreating Go4Thread ``%s'' -- old TThread %ld (PID:%d) ",
221 GetName(), fiThreadSelfID, fiThreadPID);
222 if(fxThread)
223 {
224 GO4TRACE((13,"TGo4Thread::ReCreate() -- recreating existing TThread",__LINE__, __FILE__));
225 Stop();// halt runnable
226 oldthread=fxThread; // remember old TThread
227 // first start new TThread of same Threadfunc and runnable:
228 fxThread= new TThread(GetName(),
229 (void(*) (void *)) &Threadfunc ,
230 (void *) this);
231
232 // then kill the old TThread, so Threadfunc may ReCreate() itself
233 fbIsCreated=kFALSE;
234 if(fbIsWaiting)
235 {
236 fxCondition->Signal(); // unlock condition mutex before deleting it
237 // this will not start the runnable, fbIsRunning still false
238 //fbIsWaiting=kFALSE; // keep flag consistent with Threadfunc state..
239 }
240 TThread::Delete(oldthread);
241 //delete oldthread;
242 fbIsCreated=kTRUE;
243 fxThread->Run(); // does this work if thread recreates itself?
244 Start(); // start runnable in new TThread
245
246 }
247 else
248 {
249 GO4TRACE((13,"TGo4Thread::ReCreate() -- Error: old TThread pointer is zero!",__LINE__, __FILE__));
250 TGo4Log::Debug(" Go4Thread ``%s'' ReCreate -- Internal inconsistency error! ",GetName());
251 throw TGo4RuntimeException();
252 }
253 return kTRUE;
254 }
255 else //if(fbIsCreated)
256 // no old thread, then create new one
257 {
258 GO4TRACE((13,"TGo4Thread::ReCreate() -- old TThread existing",__LINE__, __FILE__));
259 Create();
260 return kFALSE;
261 }
262}
263
265{
266 GO4TRACE((12,"TGo4Thread::Start()",__LINE__, __FILE__));
267 if (!fbIsCreated) {
268 // check if thread is up
269 // not yet created, then do so
270 GO4TRACE((11,"TGo4Thread::Start() -- creating new TThread",__LINE__, __FILE__));
271 Create();
272 } else {
273 // do nothing, thread already there
274 GO4TRACE((11,"TGo4Thread::Start() -- TThread already existing",__LINE__, __FILE__));
275 }
276 Bool_t old = fbIsRunning;
277 fbIsRunning = kTRUE;
278 fxCondition->Signal(); // wake up waiting threadfunction
279 return old; // old status of workfunc requested by thread list
280}
281
283{
284 GO4TRACE((12,"TGo4Thread::Stop()",__LINE__, __FILE__));
285 Bool_t old = fbIsRunning;
286 fbIsRunning = kFALSE;
287 return old; // old status of workfunc requested by thread list
288}
289
290void TGo4Thread::Sleep (UInt_t millisecs)
291{
292 GO4TRACE((12,"TGo4Thread::Sleep()",__LINE__, __FILE__));
293 gSystem->Sleep(millisecs);
294 TThread::CancelPoint();
295}
296
298{
299 fiThreadSelfID = TThread::SelfId();
300}
301
303{
304 fiThreadPID = gSystem->GetPid();
305}
#define GO4TRACE(X)
Definition TGo4Log.h:25
static void Debug(const char *text,...) GO4_PRINTF_ARGS
User shortcut for message with prio 0.
Definition TGo4Log.cxx:281
Base class for all go4 runnables.
virtual void ThreadCatch(TGo4Exception &ex)
catch for exceptions occurring in workfunc
virtual Int_t PostRun(void *ptr)
Function which is called once after the Run()method on threadstop.
virtual Int_t Run(void *ptr)=0
The working function which runs in the thread.
virtual Int_t PreRun(void *ptr)
Function which is called once before the Run() method on threadstart.
Bool_t Stop()
resets running flag for runnable
TCondition * fxCondition
Definition TGo4Thread.h:144
Int_t fiThreadPID
Linux process id associated with the pthread.
Definition TGo4Thread.h:125
Bool_t fbIsCreated
kTRUE if TThread instance exists and pthread is created
Definition TGo4Thread.h:119
void SetWaiting(Bool_t mode=kTRUE)
Definition TGo4Thread.h:109
Bool_t fbIsWaiting
true if Threadfunc is suspended to condition wait
Definition TGo4Thread.h:131
TThread * fxThread
Definition TGo4Thread.h:142
Long_t GetSelfID() const
self id of the current thread
Definition TGo4Thread.h:77
Bool_t IsCreated() const
kTRUE if TThread instance exists and pthread is created
Definition TGo4Thread.h:84
Long_t fiThreadSelfID
self id of the current thread
Definition TGo4Thread.h:128
Bool_t Cancel()
Cancels TThread.
TGo4Runnable * fxRunnable
External class providing the threaded workfunction and exception routines for workfunction.
Definition TGo4Thread.h:140
Bool_t fbIsRunning
Flag that controls Workfunc loop within Threadfunc.
Definition TGo4Thread.h:122
Bool_t Create()
creates the TThread if not yet existing
Bool_t fbIsInternal
specifies whether thread is internal thread of handler (true) or is owned by external class (false).
Definition TGo4Thread.h:116
TGo4Runnable * GetRunnable() const
We need this to have access to instance runnable from static Threadfunc:
Definition TGo4Thread.h:101
static void Sleep(UInt_t millisecs)
wrapper for gSystem->Sleep with consecutive TThread::CancelPoint - necessary for proper pthread termi...
Bool_t ReCreate()
Stops old Runnable; Creates new TThread of same Runnable and name; cancels old Thread.
Bool_t Start()
starts runnable method Run within thread loop by setting running flag and signaling condition
TGo4Thread()=delete
void SetSelfID()
void SetPID()
Int_t GetPID() const
linux process id associated with the pthread
Definition TGo4Thread.h:74
virtual ~TGo4Thread()
static void Threadfunc(void *arg)
This function is passed to TThread ctor and runs as pthread.
TCondition * GetCondition() const
Definition TGo4Thread.h:103
Bool_t IsRunning() const
Flag that controls Workfunc loop within Threadfunc.
Definition TGo4Thread.h:87