GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4ThreadHandler.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 "TGo4ThreadHandler.h"
15 
16 #include "TGo4Thread.h"
17 #include "TObjArray.h"
18 #include "TMutex.h"
19 
20 #include "TGo4Log.h"
21 #include "TGo4LockGuard.h"
22 #include "TGo4ThreadManager.h"
23 
25  : TNamed(right)
26 {
27  GO4TRACE((15,"TGo4ThreadHandler::TGo4ThreadHandler() copy constructor",__LINE__, __FILE__));
28  fxManager = right.fxManager;
29  fxListMutex=new TMutex;
30  fxOperMutex=new TMutex;
31  fxArray= (TObjArray *) ((right.fxArray)->Clone());
32  fxIterator=fxArray->MakeIterator();
33 }
34 
36  :TNamed(name,"This is a TGo4ThreadHandler"),fbIsOperating(kFALSE)
37 {
38  GO4TRACE((15,"TGo4ThreadHandler::TGo4ThreadHandler(const char*, TGo4ThreadManager *) constructor",__LINE__, __FILE__));
39  fxManager=parent;
40  fxListMutex=new TMutex;
41  fxOperMutex=new TMutex;
42  fxArray=new TObjArray;
43  fxIterator=fxArray->MakeIterator();
44 }
45 
46 
48 {
49  GO4TRACE((15,"TGo4ThreadHandler::~TGo4ThreadHandler() destructor",__LINE__, __FILE__));
50  StopAll();
51  CancelAll();
52  TGo4Thread *th = nullptr;
53  {
54  TGo4LockGuard listguard(fxListMutex);
55  fxIterator->Reset();
56  while((th = (TGo4Thread*) fxIterator->Next()) != nullptr)
57  {
58  if(th->IsInternal())
59  // internal mode? then delete thread object
60  {
61  GO4TRACE((14,"TGo4ThreadHandler::~TGo4ThreadHandler() Removing internal mode thread",__LINE__, __FILE__));
62  fxArray->Remove(th);
63  fxArray->Compress();
64  fxArray->Expand(fxArray->GetLast()+1);
65  delete th;
66  }
67  else
68  {
69  // do nothing
70  GO4TRACE((14,"TGo4ThreadHandler::~TGo4ThreadHandler() Non internal mode thread",__LINE__, __FILE__));
71  }
72  }// while(th=...)
73  delete fxIterator;
74  fxArray->Clear(); // remove objects from array, but do not delete them
75  delete fxArray;
76  }
77  delete fxListMutex;
78  delete fxOperMutex;
79 }
80 
81 
83 {
84  GO4TRACE((14, "TGo4ThreadHandler::AddThread(TGo4Thread *)", __LINE__, __FILE__));
85  Bool_t rev = kFALSE;
86  {
87  TGo4LockGuard listguard(fxListMutex);
88  // is thread already in list?
89  if (!fxArray->FindObject(gthr)) {
90  // no, add new thread
91  GO4TRACE((13, "TGo4ThreadHandler::AddThread(TGo4Thread*) Adding new go4 thread to array", __LINE__, __FILE__));
92  fxArray->AddLast(gthr);
93  rev = kTRUE;
94  } else {
95  // yes, do nothing
96  GO4TRACE((13, "TGo4ThreadHandler::AddThread(TGo4Thread*) Thread was already in array", __LINE__, __FILE__));
97  rev = kFALSE;
98  }
99  }
100  return rev;
101 }
102 
103 Bool_t TGo4ThreadHandler::RemoveThread (const char *name)
104 {
105  GO4TRACE((14,"TGo4ThreadHandler::RemoveThread(const char *)",__LINE__, __FILE__));
106  Bool_t rev = kFALSE;
107  {
108  TGo4LockGuard listguard(fxListMutex);
109  TObject *obj = fxArray->FindObject(name);
110  TGo4Thread *th = (TGo4Thread*) obj;
111  if (obj) {
112  // thread found, then remove it
113  GO4TRACE((13, "TGo4ThreadHandler::RemoveThread(const char *) Removing thread from array", __LINE__, __FILE__));
114  fxArray->Remove(obj);
115  fxArray->Compress();
116  fxArray->Expand(fxArray->GetLast() + 1);
117  if (th->IsInternal()) {
118  // internal mode? then delete thread
119  GO4TRACE((13, "TGo4ThreadHandler::RemoveThread(const char *) Deleting internal mode thread", __LINE__, __FILE__));
120  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
121  fbIsOperating = kTRUE;
122  fxManager->UnBlockApp(); // tell blocking timer to enable system
123  delete th;
124  fbIsOperating = kFALSE;
125  fxManager->BlockApp(); // blocking again
126  } else {
127  // do nothing
128  GO4TRACE((13, "TGo4ThreadHandler::RemoveThread(const char *) Non internal mode thread is not deleted", __LINE__, __FILE__));
129  }
130  rev = kTRUE;
131  } else {
132  GO4TRACE((13, "TGo4ThreadHandler::RemoveThread(const char *) Thread not found in array", __LINE__, __FILE__));
133  rev = kFALSE;
134  }
135  }
136  return rev;
137 }
138 
139 Bool_t TGo4ThreadHandler::NewThread(const char *name, TGo4Runnable *runnable)
140 {
141  GO4TRACE((14,"TGo4ThreadHandler::NewThread(const char*,TGo4Runnable *)",__LINE__, __FILE__));
142  TGo4Runnable *nrun = nullptr;
143  TGo4Thread *nthread = nullptr;
144  if(!runnable)
145  {
146  GO4TRACE((13,"TGo4ThreadHandler::NewThread(const char*,TGo4Runnable *) No runnable specified error",__LINE__, __FILE__));
147  return kFALSE;
148  //throw TGo4RuntimeException();
149  }
150  else
151  {
152  GO4TRACE((13,"TGo4ThreadHandler::NewThread(const char*,TGo4Runnable *) Assigning external runnable to new internal thread",__LINE__, __FILE__));
153  nrun=runnable;
154  }
155  nthread= new TGo4Thread(name,nrun,kTRUE);
156  return AddThread(nthread);
157 }
158 
160 {
161  GO4TRACE((15,"TGo4ThreadHandler::CreateAll()",__LINE__, __FILE__));
162  Int_t createdthreads = 0; // return value: number of creation successes
163  TGo4Thread *th = nullptr;
164  {
165  TGo4LockGuard listguard(fxListMutex); // protect thread list array
166  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
167  fbIsOperating=kTRUE;
168  fxManager->UnBlockApp(); // tell blocking timer to enable system
169  fxIterator->Reset();
170  while((th = (TGo4Thread*) fxIterator->Next()) != nullptr)
171  {
172  if(th->Create())
173  {
174  GO4TRACE((13,"TGo4ThreadHandler::CreateAll() Thread creation success",__LINE__, __FILE__));
175  ++createdthreads; // increment success counter
176  }
177  else
178  {
179  GO4TRACE((13,"TGo4ThreadHandler::CreateAll() Thread not created",__LINE__, __FILE__));
180  // thread was already up, no new thread created
181  }
182  }
183  fxManager->BlockApp(); // tell blocking timer to enable system
184  fbIsOperating=kFALSE;
185  }
186  return createdthreads;
187 }
188 
189 Bool_t TGo4ThreadHandler::Create (const char *thname)
190 {
191  GO4TRACE((14,"TGo4ThreadHandler::Create(const char *)",__LINE__, __FILE__));
192  Bool_t rev=kFALSE;
193  TGo4Thread *th = GetThread(thname);
194  if(th)
195  // thread was found in list
196  {
197  GO4TRACE((13,"TGo4ThreadHandler::Create(const char *) Creating new TThread for Go4Thread",__LINE__, __FILE__));
198  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
199  fbIsOperating=kTRUE;
200  fxManager->UnBlockApp(); // tell blocking timer to enable system
201  rev=th->Create();
202  fbIsOperating=kFALSE;
203  fxManager->BlockApp(); // block again afterwards
204  }
205  else
206  // no such thread
207  {
208  GO4TRACE((13,"TGo4ThreadHandler::Create(const char *) Go4Thread was not found in thread array!",__LINE__, __FILE__));
209  rev=kFALSE;
210  }
211  return rev;
212 }
213 
215 {
216  GO4TRACE((15,"TGo4ThreadHandler::CancelAll()",__LINE__, __FILE__));
217  Int_t cancelledthreads = 0; // return value: number of successes
218  TGo4Thread *th = nullptr;
219  {
220  TGo4LockGuard listguard(fxListMutex);
221  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
222  fbIsOperating = kTRUE;
223  fxIterator->Reset();
224  while ((th = (TGo4Thread *)fxIterator->Next()) != nullptr) {
225  if (th->Cancel()) {
226  GO4TRACE((13, "TGo4ThreadHandler::CancelAll() Thread Cancel success", __LINE__, __FILE__));
227  ++cancelledthreads; // increment success counter
228  } else {
229  // thread was already down, not cancelled
230  GO4TRACE((13, "TGo4ThreadHandler::CancelAll() Thread was not canceled", __LINE__, __FILE__));
231  }
232  }
233  fbIsOperating = kFALSE;
234  }
235  return cancelledthreads;
236 }
237 
238 Bool_t TGo4ThreadHandler::Cancel (const char *thname)
239 {
240  GO4TRACE((14,"TGo4ThreadHandler::Cancel(const char *)",__LINE__, __FILE__));
241  Bool_t rev = kFALSE;
242  TGo4Thread *th = GetThread(thname);
243  if (th) {
244  // go4thread was found in list
245  GO4TRACE((13, "TGo4ThreadHandler::Cancel(const char *) Canceling TThread", __LINE__, __FILE__));
246  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
247  fbIsOperating = kTRUE;
248  fxManager->UnBlockApp(); // tell blocking timer to enable system
249  rev = th->Cancel();
250  fbIsOperating = kFALSE;
251  fxManager->BlockApp(); // blocking again
252  } else {
253  // no such go4thread
254  GO4TRACE((13, "TGo4ThreadHandler::Cancel(const char *) Go4Thread was not found in thread array!", __LINE__, __FILE__));
255  rev = kFALSE;
256  }
257  return rev;
258 }
259 
261 {
262  GO4TRACE((15,"TGo4ThreadHandler::ReCreateAll()",__LINE__, __FILE__));
263  Int_t recreatedthreads = 0; // return value: number of creation successes
264  TGo4Thread *th = nullptr;
265  {
266  TGo4LockGuard listguard(fxListMutex);
267  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
268  fbIsOperating=kTRUE;
269  fxIterator->Reset();
270  while((th = (TGo4Thread*) fxIterator->Next()) != nullptr)
271  {
272  if(th->ReCreate())
273  {
274  GO4TRACE((13,"TGo4ThreadHandler::ReCreateAll() Thread ReCreate success",__LINE__, __FILE__));
275  ++recreatedthreads; // increment success counter
276  }
277  else
278  {
279  // thread was already up, no new thread created
280  GO4TRACE((13,"TGo4ThreadHandler::ReCreateAll() Thread was not recreated",__LINE__, __FILE__));
281 
282  }
283  }
284  fbIsOperating=kFALSE;
285  }
286  return recreatedthreads;
287 }
288 
289 Bool_t TGo4ThreadHandler::ReCreate (const char *thname)
290 {
291  GO4TRACE((14,"TGo4ThreadHandler::ReCreate(const char *)",__LINE__, __FILE__));
292  Bool_t rev = kFALSE;
293  TGo4Thread *th = GetThread(thname);
294  if(th)
295  // thread was found in list
296  {
297  GO4TRACE((13,"TGo4ThreadHandler::ReCreate(const char *) ReCreating TThread for Go4Thread",__LINE__, __FILE__));
298  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
299  fbIsOperating=kTRUE;
300  fxManager->UnBlockApp(); // tell blocking timer to enable system
301  rev=th->ReCreate();
302  fbIsOperating=kFALSE;
303  fxManager->BlockApp(); // block again afterwards
304  }
305  else
306  // no such thread
307  {
308  GO4TRACE((13,"TGo4ThreadHandler::ReCreate(const char *) Go4Thread was not found in thread array!",__LINE__, __FILE__));
309  rev=kFALSE;
310  }
311 
312  return rev;
313 }
314 
316 {
317  GO4TRACE((15,"TGo4ThreadHandler::StartAll()",__LINE__, __FILE__));
318  Int_t startedfuncs = 0; // return value: number of successes
319  TGo4Thread *th = nullptr;
320  {
321  TGo4LockGuard listguard(fxListMutex);
322  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
323  fbIsOperating = kTRUE; // Start has Create option, so we need gSystem
324  fxManager->UnBlockApp(); // tell blocking timer to enable system
325  fxIterator->Reset();
326  while ((th = (TGo4Thread *)fxIterator->Next()) != nullptr) {
327  if (!th->Start())
328  // StartWork returns fbFuncrun status _before_ call
329  // false: Workfunc was started from stopped status
330  {
331  // false: Workfunc was started from stopped status
332  GO4TRACE((13, "TGo4ThreadHandler::StartAll() Thread Start success", __LINE__, __FILE__));
333  ++startedfuncs; // increment success counter
334  } else {
335  // true:
336  // function was already running before
337  GO4TRACE((13, "TGo4ThreadHandler::StartAll() Thread was already running", __LINE__, __FILE__));
338  }
339  }
340  fbIsOperating = kFALSE;
341  fxManager->BlockApp();
342  }
343  return startedfuncs;
344 }
345 
346 Bool_t TGo4ThreadHandler::Start (const char *thname)
347 {
348  GO4TRACE((14,"TGo4ThreadHandler::Start(const char *)",__LINE__, __FILE__));
349  Bool_t rev = kFALSE;
350  TGo4Thread *th = GetThread(thname);
351  if(th)
352  // thread was found in list
353  {
354  GO4TRACE((13,"TGo4ThreadHandler::Start(const char *) Starting Thread",__LINE__, __FILE__));
355  TGo4LockGuard operguard(fxOperMutex); // protect operating flag
356  fbIsOperating=kTRUE; // Start has Create option, so we need gSystem
357  fxManager->UnBlockApp(); // tell blocking timer to enable system
358  rev=th->Start();
359  fbIsOperating=kFALSE;
360  fxManager->BlockApp(); // tell blocking timer to block system
361  }
362  else
363  // no such thread
364  {
365  GO4TRACE((13,"TGo4ThreadHandler::Start(const char *) Go4Thread was not found in thread array!",__LINE__, __FILE__));
366  rev=kFALSE;
367  }
368  return rev;
369 }
370 
372 {
373  GO4TRACE((15,"TGo4ThreadHandler::StopAll()",__LINE__, __FILE__));
374  Int_t stoppedfuncs = 0; // return value: number of successes
375  TGo4Thread *th = nullptr;
376  {
377  TGo4LockGuard listguard(fxListMutex);
378  fxIterator->Reset();
379  while((th= (TGo4Thread*) fxIterator->Next()) != nullptr)
380  {
381  if(th->Stop())
382  // StopWork returns fbFuncrun status _before_ call
383  {
384  // true: Workfunc was stopped from running status
385  GO4TRACE((13,"TGo4ThreadHandler::StopAll() Go4Thread Stop success",__LINE__, __FILE__));
386  ++stoppedfuncs; // increment success counter
387  }
388  else
389  {
390  // false:
391  // function was already stopped before
392  GO4TRACE((13,"TGo4ThreadHandler::StopAll() Go4Thread was already stopped",__LINE__, __FILE__));
393  }
394  }
395  }
396  return stoppedfuncs;
397 }
398 
399 Bool_t TGo4ThreadHandler::Stop (const char *thname)
400 {
401  GO4TRACE((14,"TGo4ThreadHandler::Stop(const char *)",__LINE__, __FILE__));
402  Bool_t rev=kFALSE;
403  TGo4Thread *th=GetThread(thname);
404  if(th)
405  // thread was found in list
406  {
407  GO4TRACE((13,"TGo4ThreadHandler::Stop(const char *) Stopping Go4Runnable",__LINE__, __FILE__));
408  rev=th->Stop();
409  }
410  else
411  // no such thread
412  {
413  GO4TRACE((13,"TGo4ThreadHandler::Stop(const char *) Go4Thread was not found in thread array!",__LINE__, __FILE__));
414  rev=kFALSE;
415  }
416  return rev;
417 }
418 
420 {
421  GO4TRACE((15,"TGo4ThreadHandler::DumpThreads(Int_t)",__LINE__, __FILE__));
422  if(TGo4Log::GetIgnoreLevel()>0) return 2; // only write threaddumpfile for debug mode
423  Int_t retval = 0;
424  TGo4Thread *th = nullptr;
425  FILE* fp = nullptr;
426  Int_t i = 0;
427  char Filename[80];
428  switch(mode)
429  {
430  case 0:
431  {
432  GO4TRACE((14,"TGo4ThreadHandler::DumpThreads(Int_t) mode 0: File output",__LINE__, __FILE__));
433  strcpy(Filename,"threaddump.txt");
434  fp = fopen(Filename,"w");
435  if (!fp)
436  {
437  GO4TRACE((13,"TGo4ThreadHandler::DumpThreads(Int_t) fopen failed!!",__LINE__, __FILE__));
438  TGo4Log::Debug(" ThreadHandler -- Error, Could not open thread dump file!");
439  retval=1;
440  break;
441  }
442  else
443  {
444  GO4TRACE((13,"TGo4ThreadHandler::DumpThreads(Int_t) writing into opened file",__LINE__, __FILE__));
445  fprintf(fp,"\nTGo4ThreadHandler thread information dump file:\n");
446  {
447  TGo4LockGuard listguard(fxListMutex);
448  fxIterator->Reset();
449  while((th = (TGo4Thread*) fxIterator->Next()) != nullptr)
450  {
451  fprintf(fp,"TGo4Thread %d: \tPID:%d \tSelfID: %d",
452  i++,th->GetPID(),(int) th->GetSelfID());
453  fprintf(fp,"\t name: %s\n",th->GetName());
454  }
455  }
456  if (fclose(fp))
457  {
458  GO4TRACE((13,"TGo4ThreadHandler::DumpThreads(Int_t) fclose failed!!",__LINE__, __FILE__));
459  TGo4Log::Debug(" ThreadHandlerr -- Error, Could not close thread dump file!");
460  retval=1;
461  }
462  } // if(!fp)/else
463  }//case 0:
464  break;
465  default:
466  {
467  GO4TRACE((14,"TGo4ThreadHandler::DumpThreads(Int_t) mode: default ",__LINE__, __FILE__));
468  TGo4Log::Debug(" ThreadHandlerr -- Error: DumpThreads mode unknown ");
469  }
470  break;
471  }// switch(mode)
472  return retval;
473 }
474 
476 {
477  GO4TRACE((12,"TGo4ThreadHandler::GetThread(const char *)",__LINE__, __FILE__));
478  TGo4Thread *thread = nullptr;
479  {
480  TGo4LockGuard listguard(fxListMutex);
481  thread = (TGo4Thread*) fxArray->FindObject(name);
482  }
483  return thread;
484 }
485 
487 {
488  GO4TRACE((12,"TGo4ThreadHandler::GetEntries()",__LINE__, __FILE__));
489  Int_t entries = 0;
490  {
491  TGo4LockGuard listguard(fxListMutex);
492  entries = fxArray->GetEntries();
493  }
494  return entries;
495 }
496 
498 {
499  GO4TRACE((14,"TGo4ThreadHandler::AllCreated()",__LINE__, __FILE__));
500  Bool_t rev=kTRUE; // return value: false if one thread is not there
501  TGo4Thread *th = nullptr;
502  {
503  TGo4LockGuard listguard(fxListMutex);
504  fxIterator->Reset();
505  while((th= (TGo4Thread*) fxIterator->Next()) != nullptr)
506  {
507  if((th->GetPID()) == 0)
508  {
509  GO4TRACE((11,"TGo4ThreadHandler::AllCreated() TThread is _not_ existing",__LINE__, __FILE__));
510  rev=kFALSE; // this thread is not there
511  break;
512  }
513  else
514  {
515  GO4TRACE((11,"TGo4ThreadHandler::AllCreated() TThread is existing",__LINE__, __FILE__));
516  // thread PID found
517  }
518  } // while(th=...)
519  }
520  return rev;
521 }
522 
524 {
525  GO4TRACE((14,"TGo4ThreadHandler::AllRunning()",__LINE__, __FILE__));
526  Bool_t rev=kTRUE; // return value: false if one thread is not there
527  TGo4Thread *th = nullptr;
528  {
529  TGo4LockGuard listguard(fxListMutex);
530  fxIterator->Reset();
531  while((th= (TGo4Thread*) fxIterator->Next()) != nullptr)
532  {
533  if(!(th->IsRunning()))
534  {
535  GO4TRACE((11,"TGo4ThreadHandler::AllCreated() TGo4Thread is _not_ running",__LINE__, __FILE__));
536  rev=kFALSE; // this thread is not working
537  break;
538  }
539  else
540  {
541  GO4TRACE((11,"TGo4ThreadHandler::AllCreated() TGo4Thread is running",__LINE__, __FILE__));
542  // thread is working
543  }
544  }
545  }
546  return rev;
547 }
548 
550 {
551  GO4TRACE((14,"TGo4ThreadHandler::AllWaiting()",__LINE__, __FILE__));
552  Bool_t rev=kTRUE; // return value: false if one runnable is still running
553  TGo4Thread *th = nullptr;
554  {
555  TGo4LockGuard listguard(fxListMutex);
556  fxIterator->Reset();
557  while((th = (TGo4Thread*) fxIterator->Next()) != nullptr) {
558  if(!(th->IsWaiting())) {
559  GO4TRACE((11,"TGo4ThreadHandler::AllCreated() TGo4Thread is still running",__LINE__, __FILE__));
560  rev=kFALSE; // this runnable is still doing
561  break;
562  } else {
563  GO4TRACE((11,"TGo4ThreadHandler::AllCreated() TGo4Thread is waiting",__LINE__, __FILE__));
564  // runnable is waiting
565  }
566  }
567  }
568  return rev;
569 }
TGo4Thread * GetThread(const char *name)
Bool_t Stop()
Definition: TGo4Thread.cxx:287
TGo4ThreadManager * fxManager
Bool_t UnBlockApp(Int_t mode=0)
Int_t GetEntries() const
Bool_t Cancel()
Definition: TGo4Thread.cxx:183
Bool_t ReCreate(const char *thname)
Bool_t NewThread(const char *name, TGo4Runnable *runnable)
Int_t DumpThreads(Int_t mode=0)
Long_t GetSelfID() const
Definition: TGo4Thread.h:75
static void Debug(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:281
Bool_t IsRunning() const
Definition: TGo4Thread.h:85
Bool_t IsWaiting() const
Definition: TGo4Thread.h:88
Bool_t Create(const char *thname)
Bool_t Stop(const char *thname)
Bool_t Start(const char *thname)
Bool_t Cancel(const char *thname)
Bool_t ReCreate()
Definition: TGo4Thread.cxx:215
Bool_t Create()
Definition: TGo4Thread.cxx:168
#define GO4TRACE(X)
Definition: TGo4Log.h:25
static Int_t GetIgnoreLevel()
Definition: TGo4Log.cxx:338
Bool_t AddThread(TGo4Thread *gthr)
Bool_t Start()
Definition: TGo4Thread.cxx:269
Bool_t RemoveThread(const char *name)
Bool_t IsInternal() const
Definition: TGo4Thread.h:79
Int_t GetPID() const
Definition: TGo4Thread.h:72