source: trunk/MagicSoft/Mars/mbase/MTaskList.cc@ 1350

Last change on this file since 1350 was 1337, checked in by tbretz, 23 years ago
*** empty log message ***
File size: 14.8 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 12/2000 <mailto:tbretz@uni-sw.gwdg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2001
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26// //
27// MTaskList //
28// //
29// Collection of tasks. //
30// //
31// A tasklist is necessary to run the eventloop. It contains the scheduled //
32// tasks, which should be executed in your program. //
33// //
34// To add a task use AddToList. //
35// //
36// The tasklist itself is a task, too. You can add a tasklist to another //
37// tasklist. This makes sense, if you want to filter the execution of //
38// more than one task of your tasklist using the same filter. //
39// //
40// The tasks in the list are idetified by their names. If more than one //
41// task has the same name, the tasklist will still work correctly, but //
42// you might run into trouble trying to get a pointer to a task by name //
43// from the list. //
44// //
45// Warning: //
46// Be carefull if you are writing your tasklist //
47// (eg. MWriteRootFile("file.root", "MTaskList")) to a file. You may //
48// not be able to initialize a new working tasklist from a file if //
49// a) Two Paramerer containers with the same names are existing in the //
50// MParList. //
51// b) You used a container somewhere which is not part of MParList. //
52// (eg. You specified a pointer to a MH container in MFillH which is //
53// not added to the parameter list. //
54// //
55/////////////////////////////////////////////////////////////////////////////
56
57#include "MTaskList.h"
58
59#include <TClass.h>
60#include <TBaseClass.h>
61#include <TOrdCollection.h>
62
63#include "MLog.h"
64#include "MLogManip.h"
65
66#include "MParList.h"
67#include "MInputStreamID.h"
68
69ClassImp(MTaskList);
70
71// --------------------------------------------------------------------------
72//
73// the name for the task list must be the same for all task lists
74// because the task list (at the moment) is identified by exactly
75// this name in the parameter list (by MEvtLoop::SetParList)
76//
77MTaskList::MTaskList(const char *name, const char *title)
78{
79 fName = name ? name : "MTaskList";
80 fTitle = title ? title : "A list for tasks to be executed";
81
82 fTasks = new TList;
83}
84
85// --------------------------------------------------------------------------
86//
87// CopyConstructor
88// creates a new TaskList and put the contents of an existing
89// TaskList in the new TaskList.
90//
91MTaskList::MTaskList(MTaskList &ts)
92{
93 fTasks->AddAll(ts.fTasks);
94}
95
96// --------------------------------------------------------------------------
97//
98// If the 'IsOwner' bit is set (via SetOwner()) all tasks are deleted
99// by the destructor
100//
101MTaskList::~MTaskList()
102{
103 if (TestBit(kIsOwner))
104 fTasks->SetOwner();
105
106 delete fTasks;
107}
108
109// --------------------------------------------------------------------------
110//
111// If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted
112// by the destructor
113//
114void MTaskList::SetOwner(Bool_t enable)
115{
116 enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
117}
118
119
120// --------------------------------------------------------------------------
121//
122// Set the logging stream for the all tasks in the list and the tasklist
123// itself.
124//
125void MTaskList::SetLogStream(MLog *log)
126{
127 fTasks->ForEach(MTask, SetLogStream)(log);
128 MParContainer::SetLogStream(log);
129}
130
131
132// --------------------------------------------------------------------------
133//
134// schedule task for execution, whether as first task, or after
135// 'where'. 'tType' is the event type which should be processed
136//
137Bool_t MTaskList::AddToList(MTask *task, const char *type, MTask *where)
138{
139 // FIXME: We agreed to put the task into list in an ordered way.
140
141 //
142 // Sanity check
143 //
144 if (!task)
145 return kFALSE;
146
147 //
148 // Get Name of new task
149 //
150 const char *name = task->GetName();
151
152 //
153 // Check if the new task is already existing in the list
154 //
155 const TObject *objn = fTasks->FindObject(name);
156 const TObject *objt = fTasks->FindObject(task);
157
158 if (objn || objt)
159 {
160 //
161 // If the task is already in the list ignore it.
162 //
163 if (objt || objn==task)
164 {
165 *fLog << warn << dbginf << "Warning: Task '" << task->GetName() << ", 0x" << (void*)task;
166 *fLog << "' already existing in '" << GetName() << "'... ignoring." << endl;
167 return kTRUE;
168 }
169
170 //
171 // Otherwise add it to the list, but print a warning message
172 //
173 *fLog << warn << dbginf << "Warning: Task '" << task->GetName();
174 *fLog << "' already existing in '" << GetName() << "'." << endl;
175 *fLog << "You may not be able to get a pointer to this task by name." << endl;
176 }
177
178 if (where)
179 {
180 if (!fTasks->FindObject(where))
181 {
182 *fLog << err << dbginf << "Error: Cannot find task after which the new task should be scheduled!" << endl;
183 return kFALSE;
184 }
185 }
186
187 *fLog << inf << "Adding " << name << " to " << GetName() << " for " << type << "... " << flush;
188
189 task->SetStreamId(type);
190 fTasks->Add(task);
191
192 *fLog << "Done." << endl;
193
194 return kTRUE;
195}
196
197// --------------------------------------------------------------------------
198//
199// Find an object in the list.
200// 'name' is the name of the object you are searching for.
201//
202TObject *MTaskList::FindObject(const char *name) const
203{
204 return fTasks->FindObject(name);
205}
206
207// --------------------------------------------------------------------------
208//
209// check if the object is in the list or not
210//
211TObject *MTaskList::FindObject(const TObject *obj) const
212{
213 return fTasks->FindObject(obj);
214}
215
216// --------------------------------------------------------------------------
217//
218// do reinit of all tasks in the task-list
219//
220Bool_t MTaskList::ReInit(MParList *pList)
221{
222 *fLog << all << "Reinit... " << flush;
223
224 //
225 // create the Iterator over the tasklist
226 //
227 TIter Next(fTasks);
228
229 MTask *task=NULL;
230 //
231 // loop over all tasks for preproccesing
232 //
233 while ((task=(MTask*)Next()))
234 {
235 *fLog << all << task->GetName() << "... " << flush;
236
237 if (!task->ReInit(pList?pList:fParList))
238 {
239 *fLog << err << "ERROR - ReInit if Task " << task->GetDescriptor() << " failed." << endl;
240 return kFALSE;
241 }
242 }
243
244 *fLog << all << endl;
245
246 return kTRUE;
247}
248
249// --------------------------------------------------------------------------
250//
251// removes a task from the list (used in PreProcess).
252// if kIsOwner is set the task is deleted. (see SetOwner())
253//
254void MTaskList::Remove(MTask *task)
255{
256 TObject *obj = fTasks->Remove(task);
257
258 if (TestBit(kIsOwner))
259 delete obj;
260}
261
262// --------------------------------------------------------------------------
263//
264// Check whether this task (or one of it's base classes) overloads
265// MTask::Process. Only if this function is overloaded this task is
266// added to the fTaskProcess-List. This makes the execution of the
267// tasklist a little bit (only a little bit) faster, bacause tasks
268// doing no Processing are not Processed.
269//
270Bool_t MTaskList::CheckClassForProcess(TClass *cls)
271{
272 //
273 // Check whether the class itself overloads the Process function
274 //
275 if (cls->GetName()=="MTask")
276 return kFALSE;
277
278 if (cls->GetMethodAny("Process"))
279 return kTRUE;
280
281 //
282 // If the class itself doesn't overload it check all it's base classes
283 //
284 TBaseClass *base=NULL;
285 TIter NextBase(cls->GetListOfBases());
286 while ((base=(TBaseClass*)NextBase()))
287 {
288 if (CheckClassForProcess(base->GetClassPointer()))
289 return kTRUE;
290 }
291
292 return kFALSE;
293}
294
295// --------------------------------------------------------------------------
296//
297// do pre processing (before eventloop) of all tasks in the task-list
298//
299Bool_t MTaskList::PreProcess(MParList *pList)
300{
301 *fLog << all << "Preprocessing... " << flush;
302
303 fParList = pList;
304
305 fTasksProcess.Clear();
306
307 //
308 // create the Iterator over the tasklist
309 //
310 TIter Next(fTasks);
311
312 MTask *task=NULL;
313
314 //
315 // loop over all tasks for preproccesing
316 //
317 while ((task=(MTask*)Next()))
318 {
319 *fLog << all << task->GetName() << "... " << flush;
320
321 if (CheckClassForProcess(task->IsA()))
322 fTasksProcess.Add(task);
323
324 //
325 // PreProcess the task and check for it's return value.
326 //
327 switch (task->CallPreProcess(fParList))
328 {
329 case kFALSE:
330 return kFALSE;
331
332 case kTRUE:
333 continue;
334
335 case kSKIP:
336 Remove(task);
337 continue;
338 }
339
340 *fLog << err << dbginf << "PreProcess of " << task->GetDescriptor();
341 *fLog << " returned an unknown value... aborting." << endl;
342 return kFALSE;
343 }
344
345 *fLog << all << endl;
346
347 return kTRUE;
348}
349
350// --------------------------------------------------------------------------
351//
352// do the event execution of all tasks in the task-list
353//
354Bool_t MTaskList::Process()
355{
356 //
357 // Check whether there is something which can be processed, otherwise
358 // stop the eventloop.
359 //
360 if (fTasksProcess.GetSize()==0)
361 {
362 *fLog << warn << "Warning: No entries in " << GetDescriptor() << " for Processing." << endl;
363 return kFALSE;
364 }
365
366 //
367 // Reset the ReadyToSave flag.
368 // Reset all containers.
369 //
370 // FIXME: To run a tasklist as a single task in another tasklist we
371 // have to make sure, that the Parameter list isn't reset.
372 //
373 fParList->SetReadyToSave(kFALSE);
374 fParList->Reset();
375
376 //
377 // create the Iterator for the TaskList
378 //
379 TIter Next(&fTasksProcess);
380 MTask *task=NULL;
381
382 //
383 // loop over all tasks for processing
384 //
385 while ( (task=(MTask*)Next()) )
386 {
387 //
388 // if the task has the wrong stream id skip it.
389 //
390 if (GetStreamId() != task->GetStreamId() &&
391 task->GetStreamId() != "All")
392 continue;
393
394 //
395 // if it has the right stream id execute the CallProcess() function
396 // and check what the result of it is.
397 // The CallProcess() function increases the execution counter and
398 // calls the Process() function dependent on the existance and
399 // return value of a filter.
400 //
401 switch (task->CallProcess())
402 {
403 case kTRUE:
404 //
405 // everything was OK: go on with the next task
406 //
407 continue;
408
409 case kFALSE:
410 //
411 // an error occured: stop eventloop
412 //
413 return kFALSE;
414
415 case kCONTINUE:
416 //
417 // something occured: skip the rest of the tasks for this event
418 //
419 return kTRUE;
420
421 default:
422 *fLog << warn << "MTaskList::Process: Unknown return value from MTask::Process()... ignored." << endl;
423 }
424 }
425
426 return kTRUE;
427}
428
429// --------------------------------------------------------------------------
430//
431// do post processing (before eventloop) of all tasks in the task-list
432// only tasks which have successfully been preprocessed are postprocessed.
433//
434Bool_t MTaskList::PostProcess()
435{
436 *fLog << all << "Postprocessing... " << flush;
437
438 //
439 // Reset the ReadyToSave flag.
440 // Reset all containers.
441 //
442 // FIXME: To run a tasklist as a single task in another tasklist we
443 // have to make sure, that the Parameter list isn't reset.
444 //
445 fParList->SetReadyToSave(kFALSE);
446 fParList->Reset();
447
448 //
449 // create the Iterator for the TaskList
450 //
451 TIter Next(fTasks);
452
453 MTask *task=NULL;
454
455 //
456 // loop over all tasks for postprocessing
457 // only tasks which have successfully been preprocessed are postprocessed.
458 //
459 while ( (task=(MTask*)Next()) )
460 {
461 *fLog << all << task->GetName() << "... " << flush;
462
463 if (!task->CallPostProcess())
464 return kFALSE;
465 }
466
467 *fLog << all << endl;
468
469 return kTRUE;
470}
471
472// --------------------------------------------------------------------------
473//
474// Prints the number of times all the tasks in the list has been.
475// For convinience the lvl argument results in a number of spaces at the
476// beginning of the line. So that the structur of a tasklist can be
477// identified. Use MTaskList::PrintStatistics without an argument.
478//
479void MTaskList::PrintStatistics(const Int_t lvl) const
480{
481 if (lvl==0)
482 {
483 *fLog << all << endl;
484 *fLog << "Execution Statistics: " << endl;
485 *fLog << "---------------------" << endl;
486 *fLog << GetDescriptor() << endl;
487 }
488 else
489 {
490 *fLog << setw(lvl) << " " << GetDescriptor() << endl;
491 }
492
493 //
494 // create the Iterator for the TaskList
495 //
496 fTasks->ForEach(MTask, PrintStatistics)(lvl+1);
497
498 if (lvl==0)
499 *fLog << endl;
500}
501
502// --------------------------------------------------------------------------
503void MTaskList::Print(Option_t *t) const
504{
505 *fLog << all << endl;
506 *fLog << GetDescriptor() << endl;
507 *fLog << setfill('-') << setw(strlen(GetDescriptor())) << "" << endl;
508
509 fTasks->Print();
510
511 *fLog << endl;
512}
513
Note: See TracBrowser for help on using the repository browser.