00001 // @(#)root/base:$Id: TTask.cxx 31827 2009-12-11 07:52:09Z brun $ 00002 // Author: Rene Brun 02/09/2000 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 //______________________________________________________________________________ 00013 // 00014 // TTask is a base class that can be used to build a complex tree of Tasks. 00015 // Each TTask derived class may contain other TTasks that can be executed 00016 // recursively, such that a complex program can be dynamically built and executed 00017 // by invoking the services of the top level Task or one of its subtasks. 00018 // 00019 // Use the TTask::Add function to add a subtask to an existing TTask. 00020 // To execute a TTask, one calls the ExecuteTask function. ExecuteTask will 00021 // call recursively: 00022 // - the TTask::Exec function of the derived class 00023 // - TTask::ExecuteTasks to execute for each task the list of its subtasks. 00024 // If the top level task (see example below) is added to the list of Root 00025 // browsable objects, the tree of tasks can be visualized by the Root browser. 00026 // The browser can be used to start a task, set break points at the beginning 00027 // of a task or when the task has completed. At a breakpoint, data structures 00028 // generated by the execution up this point may be inspected asyncronously 00029 // and then the execution can be resumed by selecting the "Continue" function 00030 // of a task. 00031 // 00032 // A Task may be active or inactive (controlled by TTask::SetActive). 00033 // When a task is not active, its sub tasks are not executed. 00034 // 00035 // A TTask tree may be made persistent, saving the status of all the tasks. 00036 // 00037 // The picture in the Root browser below has been generated by executing 00038 // the following script: 00039 // 00040 //{ //------------------script tasks.C--------------------------- 00041 // TTask *aliroot = new TTask("aliroot","ALICE reconstruction main task"); 00042 // TTask *geominit = new TTask("geomInit","Initialize ALICE geometry"); 00043 // TTask *matinit = new TTask("matInit","Initialize ALICE materials"); 00044 // TTask *physinit = new TTask("physInit","Initialize Physics processes"); 00045 // TTask *tracker = new TTask("tracker","Track reconstruction manager"); 00046 // TTask *tpcrec = new TTask("tpcrec","TPC reconstruction"); 00047 // TTask *itsrec = new TTask("itsrec","ITS reconstruction"); 00048 // TTask *muonrec = new TTask("muonRec","Muon Reconstruction"); 00049 // TTask *phosrec = new TTask("phosRec","Phos Reconstruction"); 00050 // TTask *richrec = new TTask("richRec","Rich Reconstruction"); 00051 // TTask *trdrec = new TTask("trdRec","TRD Reconstruction"); 00052 // TTask *globrec = new TTask("globRec","Global Track Reconstruction"); 00053 // TTask *pstats = new TTask("printStats","Print Run Statistics"); 00054 // TTask *run = new TTask("run","Process one run"); 00055 // TTask *event = new TTask("event","Process one event"); 00056 // aliroot->Add(geominit); 00057 // aliroot->Add(matinit); 00058 // aliroot->Add(physinit); 00059 // aliroot->Add(run); 00060 // run->Add(event); 00061 // event->Add(tracker); 00062 // event->Add(muonrec); 00063 // event->Add(phosrec); 00064 // event->Add(richrec); 00065 // event->Add(trdrec); 00066 // event->Add(globrec); 00067 // tracker->Add(tpcrec); 00068 // tracker->Add(itsrec); 00069 // run->Add(pstats); 00070 // 00071 // gROOT->GetListOfBrowsables()->Add(aliroot,"aliroot"); 00072 // new TBrowser; 00073 //} //------------------------------------------------------------- 00074 // 00075 //Begin_Html 00076 /* 00077 <img src="gif/tasks.gif"> 00078 */ 00079 //End_Html 00080 00081 #include "Riostream.h" 00082 #include "TTask.h" 00083 #include "TBrowser.h" 00084 #include "TROOT.h" 00085 #include "TRegexp.h" 00086 00087 TTask *TTask::fgBeginTask = 0; 00088 TTask *TTask::fgBreakPoint = 0; 00089 00090 ClassImp(TTask) 00091 00092 //______________________________________________________________________________ 00093 TTask::TTask() 00094 { 00095 // Default constructor invoked when reading a TTask object from a file. 00096 00097 fHasExecuted = kFALSE; 00098 fActive = kTRUE; 00099 fBreakin = 0; 00100 fBreakout = 0; 00101 fTasks = 0; 00102 } 00103 00104 //______________________________________________________________________________ 00105 TTask::TTask(const char* name, const char *title) 00106 : TNamed(name,title) 00107 { 00108 // Standard constructor. 00109 00110 fHasExecuted = kFALSE; 00111 fActive = kTRUE; 00112 fBreakin = 0; 00113 fBreakout = 0; 00114 fTasks = new TList(); 00115 } 00116 //______________________________________________________________________________ 00117 00118 TTask& TTask::operator=(const TTask& tt) 00119 { 00120 //assignment operator (PLEASE DO NOT USE THIS IS WRONG) 00121 if(this!=&tt) { 00122 TNamed::operator=(tt); 00123 fTasks->Delete(); 00124 TIter next(tt.fTasks); 00125 TTask *task; 00126 while ((task = (TTask*)next())) { 00127 fTasks->Add(new TTask(*task)); 00128 } 00129 fOption=tt.fOption; 00130 fBreakin=tt.fBreakin; 00131 fBreakout=tt.fBreakout; 00132 fHasExecuted=tt.fHasExecuted; 00133 fActive=tt.fActive; 00134 } 00135 return *this; 00136 } 00137 00138 //______________________________________________________________________________ //______________________________________________________________________________ 00139 TTask::TTask(const TTask &other) : TNamed(other) 00140 { 00141 // Copy constructor. 00142 fTasks = new TList(); 00143 TIter next(other.fTasks); 00144 TTask *task; 00145 while ((task = (TTask*)next())) { 00146 fTasks->Add(new TTask(*task)); 00147 } 00148 fOption = other.fOption; 00149 fBreakin = other.fBreakin; 00150 fBreakout = other.fBreakout; 00151 fHasExecuted = kFALSE; 00152 fActive = other.fActive; 00153 } 00154 00155 //______________________________________________________________________________ 00156 TTask::~TTask() 00157 { 00158 // Delete a task and its subtasks. 00159 if (!fTasks) return; 00160 fTasks->Delete(); 00161 delete fTasks; 00162 } 00163 00164 //______________________________________________________________________________ 00165 void TTask::Abort() 00166 { 00167 // Abort current tree of tasks. 00168 // After this call, the tree of tasks is ready to be executed again. 00169 // The application must take care of cleaning data structures created 00170 // by previous executions. 00171 00172 if (!fgBeginTask) { 00173 printf(" Nothing to abort: No task currently running\n"); 00174 return; 00175 } 00176 CleanTasks(); 00177 fgBeginTask = 0; 00178 fgBreakPoint = 0; 00179 } 00180 00181 //______________________________________________________________________________ 00182 void TTask::Browse(TBrowser *b) 00183 { 00184 // Browse the list of tasks. 00185 // It is recommended to add the top level task to the list of 00186 // ROOT browsables by: 00187 // gROOT->GetListOfBrowsables()->Add(myTopLevelTask) 00188 00189 fTasks->Browse(b); 00190 } 00191 00192 //______________________________________________________________________________ 00193 void TTask::CleanTasks() 00194 { 00195 // Reset tasks state: breakpoints and execute flags 00196 // also invokes the Clear function of each task to clear all data 00197 // structures created by a previous execution of a task. 00198 00199 if (fBreakin) fBreakin = 1; 00200 if (fBreakout) fBreakout = 1; 00201 fHasExecuted = kFALSE; 00202 Clear(); 00203 TIter next(fTasks); 00204 TTask *task; 00205 while((task=(TTask*)next())) { 00206 task->CleanTasks(); 00207 } 00208 } 00209 00210 //______________________________________________________________________________ 00211 void TTask::Clear(Option_t *) 00212 { 00213 // Recursively call the Clear function of this task and its subtasks. 00214 // The Clear function must be implemented for each derived class 00215 // to clear all data structures created by a previous execution of a task. 00216 // This function is automatically called by the CleanTasks function. 00217 } 00218 00219 //______________________________________________________________________________ 00220 void TTask::Continue() 00221 { 00222 // Resume execution at the current break point. 00223 00224 if (!fgBeginTask) { 00225 printf(" No task to continue\n"); 00226 return; 00227 } 00228 fgBreakPoint = 0; 00229 00230 fgBeginTask->ExecuteTasks(fOption.Data()); 00231 00232 if (!fgBreakPoint) { 00233 fgBeginTask->CleanTasks(); 00234 fgBeginTask = 0; 00235 } 00236 } 00237 00238 //______________________________________________________________________________ 00239 void TTask::Exec(Option_t *) 00240 { 00241 // Dummy Execute. 00242 // This function must be redefined in the derived classes. 00243 } 00244 00245 //______________________________________________________________________________ 00246 void TTask::ExecuteTask(Option_t *option) 00247 { 00248 // Execute main task and its subtasks. 00249 // When calling this function, the Exec function of the corresponding class 00250 // is invoked, then the list of its subtasks is executed calling recursively 00251 // all the subtasks, etc. 00252 // 00253 // The option parameter may be used to select different execution steps 00254 // within a task. This parameter is passed also to all the subtasks. 00255 00256 if (fgBeginTask) { 00257 Error("ExecuteTask","Cannot execute task:%s, already running task: %s",GetName(),fgBeginTask->GetName()); 00258 return; 00259 } 00260 if (!IsActive()) return; 00261 00262 fOption = option; 00263 fgBeginTask = this; 00264 fgBreakPoint = 0; 00265 00266 if (fBreakin) return; 00267 if (gDebug > 1) { 00268 TROOT::IndentLevel(); 00269 cout<<"Execute task:"<<GetName()<<" : "<<GetTitle()<<endl; 00270 TROOT::IncreaseDirLevel(); 00271 } 00272 Exec(option); 00273 00274 fHasExecuted = kTRUE; 00275 ExecuteTasks(option); 00276 00277 if (gDebug > 1) TROOT::DecreaseDirLevel(); 00278 if (fBreakout) return; 00279 00280 if (!fgBreakPoint) { 00281 fgBeginTask->CleanTasks(); 00282 fgBeginTask = 0; 00283 } 00284 } 00285 00286 //______________________________________________________________________________ 00287 void TTask::ExecuteTasks(Option_t *option) 00288 { 00289 // Execute all the subtasks of a task. 00290 00291 TIter next(fTasks); 00292 TTask *task; 00293 while((task=(TTask*)next())) { 00294 if (fgBreakPoint) return; 00295 if (!task->IsActive()) continue; 00296 if (task->fHasExecuted) { 00297 task->ExecuteTasks(option); 00298 continue; 00299 } 00300 if (task->fBreakin == 1) { 00301 printf("Break at entry of task: %s\n",task->GetName()); 00302 fgBreakPoint = this; 00303 task->fBreakin++; 00304 return; 00305 } 00306 00307 if (gDebug > 1) { 00308 TROOT::IndentLevel(); 00309 cout<<"Execute task:"<<task->GetName()<<" : "<<task->GetTitle()<<endl; 00310 TROOT::IncreaseDirLevel(); 00311 } 00312 task->Exec(option); 00313 task->fHasExecuted = kTRUE; 00314 task->ExecuteTasks(option); 00315 if (gDebug > 1) TROOT::DecreaseDirLevel(); 00316 if (task->fBreakout == 1) { 00317 printf("Break at exit of task: %s\n",task->GetName()); 00318 fgBreakPoint = this; 00319 task->fBreakout++; 00320 return; 00321 } 00322 } 00323 } 00324 00325 //______________________________________________________________________________ 00326 void TTask::ls(Option_t *option) const 00327 { 00328 // List the tree of tasks. 00329 // Indentation is used to identify the task tree. 00330 00331 TROOT::IndentLevel(); 00332 cout <<GetName()<<"\t"<<GetTitle()<<endl; 00333 TROOT::IncreaseDirLevel(); 00334 00335 TString opta = option; 00336 TString opt = opta.Strip(TString::kBoth); 00337 00338 TRegexp re(opt, kTRUE); 00339 00340 TObject *obj; 00341 TIter nextobj(fTasks); 00342 while ((obj = (TObject *) nextobj())) { 00343 TString s = obj->GetName(); 00344 if (s.Index(re) == kNPOS) continue; 00345 obj->ls(option); 00346 } 00347 TROOT::DecreaseDirLevel(); 00348 }