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