Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTask.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Rene Brun 02/09/2000
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 TTask
13 \ingroup Base
14 
15 TTask is a base class that can be used to build a complex tree of Tasks.
16 Each TTask derived class may contain other TTasks that can be executed
17 recursively, such that a complex program can be dynamically built and executed
18 by invoking the services of the top level Task or one of its subtasks.
19 
20 Use the TTask::Add function to add a subtask to an existing TTask.
21 To execute a TTask, one calls the ExecuteTask function. ExecuteTask will
22 call recursively:
23 
24  - the TTask::Exec function of the derived class
25  - TTask::ExecuteTasks to execute for each task the list of its subtasks.
26 
27 If the top level task (see example below) is added to the list of Root
28 browsable objects, the tree of tasks can be visualized by the Root browser.
29 The browser can be used to start a task, set break points at the beginning
30 of a task or when the task has completed. At a breakpoint, data structures
31 generated by the execution up this point may be inspected asynchronously
32 and then the execution can be resumed by selecting the "Continue" function
33 of a task.
34 //
35 A Task may be active or inactive (controlled by TTask::SetActive).
36 When a task is not active, its sub tasks are not executed.
37 //
38 A TTask tree may be made persistent, saving the status of all the tasks.
39 //
40 The Root browser's picture below has been generated by executing
41 the following script:
42 ~~~ {.cpp}
43 {
44  TTask *aliroot = new TTask("aliroot","ALICE reconstruction main task");
45  TTask *geominit = new TTask("geomInit","Initialize ALICE geometry");
46  TTask *matinit = new TTask("matInit","Initialize ALICE materials");
47  TTask *physinit = new TTask("physInit","Initialize Physics processes");
48  TTask *tracker = new TTask("tracker","Track reconstruction manager");
49  TTask *tpcrec = new TTask("tpcrec","TPC reconstruction");
50  TTask *itsrec = new TTask("itsrec","ITS reconstruction");
51  TTask *muonrec = new TTask("muonRec","Muon Reconstruction");
52  TTask *phosrec = new TTask("phosRec","Phos Reconstruction");
53  TTask *richrec = new TTask("richRec","Rich Reconstruction");
54  TTask *trdrec = new TTask("trdRec","TRD Reconstruction");
55  TTask *globrec = new TTask("globRec","Global Track Reconstruction");
56  TTask *pstats = new TTask("printStats","Print Run Statistics");
57  TTask *run = new TTask("run","Process one run");
58  TTask *event = new TTask("event","Process one event");
59  aliroot->Add(geominit);
60  aliroot->Add(matinit);
61  aliroot->Add(physinit);
62  aliroot->Add(run);
63  run->Add(event);
64  event->Add(tracker);
65  event->Add(muonrec);
66  event->Add(phosrec);
67  event->Add(richrec);
68  event->Add(trdrec);
69  event->Add(globrec);
70  tracker->Add(tpcrec);
71  tracker->Add(itsrec);
72  run->Add(pstats);
73 
74  gROOT->GetListOfBrowsables()->Add(aliroot,"aliroot");
75  new TBrowser;
76 }
77 ~~~
78 \image html base_tasks.png
79 */
80 
81 #include "Riostream.h"
82 #include "TTask.h"
83 #include "TBrowser.h"
84 #include "TROOT.h"
85 #include "TRegexp.h"
86 
87 TTask *TTask::fgBeginTask = 0;
88 TTask *TTask::fgBreakPoint = 0;
89 
90 ClassImp(TTask);
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 /// Default constructor invoked when reading a TTask object from a file.
94 
95 TTask::TTask()
96 {
97  fHasExecuted = kFALSE;
98  fActive = kTRUE;
99  fBreakin = 0;
100  fBreakout = 0;
101  fTasks = 0;
102 }
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Standard constructor.
106 
107 TTask::TTask(const char* name, const char *title)
108  : TNamed(name,title)
109 {
110  fHasExecuted = kFALSE;
111  fActive = kTRUE;
112  fBreakin = 0;
113  fBreakout = 0;
114  fTasks = new TList();
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// Assignment operator.
119 
120 TTask& TTask::operator=(const TTask& tt)
121 {
122  if(this!=&tt) {
123  TNamed::operator=(tt);
124  fTasks->Delete();
125  TIter next(tt.fTasks);
126  TTask *task;
127  while ((task = (TTask*)next())) {
128  fTasks->Add(new TTask(*task));
129  }
130  fOption=tt.fOption;
131  fBreakin=tt.fBreakin;
132  fBreakout=tt.fBreakout;
133  fHasExecuted=tt.fHasExecuted;
134  fActive=tt.fActive;
135  }
136  return *this;
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// Copy constructor.
141 
142 TTask::TTask(const TTask &other) : TNamed(other)
143 {
144  fTasks = new TList();
145  TIter next(other.fTasks);
146  TTask *task;
147  while ((task = (TTask*)next())) {
148  fTasks->Add(new TTask(*task));
149  }
150  fOption = other.fOption;
151  fBreakin = other.fBreakin;
152  fBreakout = other.fBreakout;
153  fHasExecuted = kFALSE;
154  fActive = other.fActive;
155 }
156 
157 ////////////////////////////////////////////////////////////////////////////////
158 /// Delete a task and its subtasks.
159 
160 TTask::~TTask()
161 {
162  if (!fTasks) return;
163  fTasks->Delete();
164  delete fTasks;
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 /// Abort current tree of tasks.
169 /// After this call, the tree of tasks is ready to be executed again.
170 /// The application must take care of cleaning data structures created
171 /// by previous executions.
172 
173 void TTask::Abort()
174 {
175  if (!fgBeginTask) {
176  printf(" Nothing to abort: No task currently running\n");
177  return;
178  }
179  CleanTasks();
180  fgBeginTask = 0;
181  fgBreakPoint = 0;
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// Browse the list of tasks.
186 /// It is recommended to add the top level task to the list of
187 /// ROOT browsables by:
188 /// ~~~{.cpp}
189 /// gROOT->GetListOfBrowsables()->Add(myTopLevelTask)
190 /// ~~~
191 
192 void TTask::Browse(TBrowser *b)
193 {
194  fTasks->Browse(b);
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Reset tasks state: breakpoints and execute flags
199 /// also invokes the Clear function of each task to clear all data
200 /// structures created by a previous execution of a task.
201 
202 void TTask::CleanTasks()
203 {
204  if (fBreakin) fBreakin = 1;
205  if (fBreakout) fBreakout = 1;
206  fHasExecuted = kFALSE;
207  Clear();
208  TIter next(fTasks);
209  TTask *task;
210  while((task=(TTask*)next())) {
211  task->CleanTasks();
212  }
213 }
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 /// Recursively call the Clear function of this task and its subtasks.
217 /// The Clear function must be implemented for each derived class
218 /// to clear all data structures created by a previous execution of a task.
219 /// This function is automatically called by the CleanTasks function.
220 
221 void TTask::Clear(Option_t *)
222 {
223 }
224 
225 ////////////////////////////////////////////////////////////////////////////////
226 /// Resume execution at the current break point.
227 
228 void TTask::Continue()
229 {
230  if (!fgBeginTask) {
231  printf(" No task to continue\n");
232  return;
233  }
234  fgBreakPoint = 0;
235 
236  fgBeginTask->ExecuteTasks(fOption.Data());
237 
238  if (!fgBreakPoint) {
239  fgBeginTask->CleanTasks();
240  fgBeginTask = 0;
241  }
242 }
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 /// Dummy Execute.
246 /// This function must be redefined in the derived classes.
247 
248 void TTask::Exec(Option_t *)
249 {
250 }
251 
252 ////////////////////////////////////////////////////////////////////////////////
253 /// Execute main task and its subtasks.
254 /// When calling this function, the Exec function of the corresponding class
255 /// is invoked, then the list of its subtasks is executed calling recursively
256 /// all the subtasks, etc.
257 ///
258 /// The option parameter may be used to select different execution steps
259 /// within a task. This parameter is passed also to all the subtasks.
260 
261 void TTask::ExecuteTask(Option_t *option)
262 {
263  if (fgBeginTask) {
264  Error("ExecuteTask","Cannot execute task:%s, already running task: %s",GetName(),fgBeginTask->GetName());
265  return;
266  }
267  if (!IsActive()) return;
268 
269  fOption = option;
270  fgBeginTask = this;
271  fgBreakPoint = 0;
272 
273  if (fBreakin) return;
274  if (gDebug > 1) {
275  TROOT::IndentLevel();
276  std::cout<<"Execute task:"<<GetName()<<" : "<<GetTitle()<<std::endl;
277  TROOT::IncreaseDirLevel();
278  }
279  Exec(option);
280 
281  fHasExecuted = kTRUE;
282  ExecuteTasks(option);
283 
284  if (gDebug > 1) TROOT::DecreaseDirLevel();
285  if (fBreakout) return;
286 
287  if (!fgBreakPoint) {
288  fgBeginTask->CleanTasks();
289  fgBeginTask = 0;
290  }
291 }
292 
293 ////////////////////////////////////////////////////////////////////////////////
294 /// Execute all the subtasks of a task.
295 
296 void TTask::ExecuteTasks(Option_t *option)
297 {
298  TIter next(fTasks);
299  TTask *task;
300  while((task=(TTask*)next())) {
301  if (fgBreakPoint) return;
302  if (!task->IsActive()) continue;
303  if (task->fHasExecuted) {
304  task->ExecuteTasks(option);
305  continue;
306  }
307  if (task->fBreakin == 1) {
308  printf("Break at entry of task: %s\n",task->GetName());
309  fgBreakPoint = this;
310  task->fBreakin++;
311  return;
312  }
313 
314  if (gDebug > 1) {
315  TROOT::IndentLevel();
316  std::cout<<"Execute task:"<<task->GetName()<<" : "<<task->GetTitle()<<std::endl;
317  TROOT::IncreaseDirLevel();
318  }
319  task->Exec(option);
320  task->fHasExecuted = kTRUE;
321  task->ExecuteTasks(option);
322  if (gDebug > 1) TROOT::DecreaseDirLevel();
323  if (task->fBreakout == 1) {
324  printf("Break at exit of task: %s\n",task->GetName());
325  fgBreakPoint = this;
326  task->fBreakout++;
327  return;
328  }
329  }
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 /// List the tree of tasks.
334 /// Indentation is used to identify the task tree.
335 
336 void TTask::ls(Option_t *option) const
337 {
338  TROOT::IndentLevel();
339  std::cout <<GetName()<<"\t"<<GetTitle()<<std::endl;
340  TROOT::IncreaseDirLevel();
341 
342  TString opta = option;
343  TString opt = opta.Strip(TString::kBoth);
344 
345  TRegexp re(opt, kTRUE);
346 
347  TObject *obj;
348  TIter nextobj(fTasks);
349  while ((obj = (TObject *) nextobj())) {
350  TString s = obj->GetName();
351  if (s.Index(re) == kNPOS) continue;
352  obj->ls(option);
353  }
354  TROOT::DecreaseDirLevel();
355 }