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

Last change on this file since 1283 was 1283, checked in by tbretz, 23 years ago
*** empty log message ***
File size: 14.6 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 //
232 // loop over all tasks for preproccesing
233 //
234 while ((task=(MTask*)Next()))
235 {
236 *fLog << all << task->GetName() << "... " << flush;
237
238 if (!task->ReInit(pList?pList:fParList))
239 return kFALSE;
240 }
241
242 *fLog << all << endl;
243
244 return kTRUE;
245}
246
247// --------------------------------------------------------------------------
248//
249// removes a task from the list (used in PreProcess).
250// if kIsOwner is set the task is deleted. (see SetOwner())
251//
252void MTaskList::Remove(MTask *task)
253{
254 TObject *obj = fTasks->Remove(task);
255
256 if (TestBit(kIsOwner))
257 delete obj;
258}
259
260// --------------------------------------------------------------------------
261//
262// Check whether this task (or one of it's base classes) overloads
263// MTask::Process. Only if this function is overloaded this task is
264// added to the fTaskProcess-List. This makes the execution of the
265// tasklist a little bit (only a little bit) faster, bacause tasks
266// doing no Processing are not Processed.
267//
268Bool_t MTaskList::CheckClassForProcess(TClass *cls)
269{
270 //
271 // Check whether the class itself overloads the Process function
272 //
273 if (cls->GetName()=="MTask")
274 return kFALSE;
275
276 if (cls->GetMethodAny("Process"))
277 return kTRUE;
278
279 //
280 // If the class itself doesn't overload it check all it's base classes
281 //
282 TBaseClass *base=NULL;
283 TIter NextBase(cls->GetListOfBases());
284 while ((base=(TBaseClass*)NextBase()))
285 {
286 if (CheckClassForProcess(base->GetClassPointer()))
287 return kTRUE;
288 }
289
290 return kFALSE;
291}
292
293// --------------------------------------------------------------------------
294//
295// do pre processing (before eventloop) of all tasks in the task-list
296//
297Bool_t MTaskList::PreProcess(MParList *pList)
298{
299 *fLog << all << "Preprocessing... " << flush;
300
301 fParList = pList;
302
303 fTasksProcess.Delete();
304
305 //
306 // create the Iterator over the tasklist
307 //
308 TIter Next(fTasks);
309
310 MTask *task=NULL;
311
312 //
313 // loop over all tasks for preproccesing
314 //
315 while ((task=(MTask*)Next()))
316 {
317 if (CheckClassForProcess(task->IsA()))
318 fTasksProcess.Add(task);
319
320 //
321 // PreProcess the task and check for it's return value.
322 //
323 switch (task->CallPreProcess(fParList))
324 {
325 case kFALSE:
326 return kFALSE;
327
328 case kTRUE:
329 continue;
330
331 case kSKIP:
332 Remove(task);
333 continue;
334 }
335
336 *fLog << err << dbginf << "PreProcess of " << task->GetDescriptor();
337 *fLog << " returned an unknown value... aborting." << endl;
338 return kFALSE;
339 }
340
341 *fLog << all << endl;
342
343 return kTRUE;
344}
345
346// --------------------------------------------------------------------------
347//
348// do the event execution of all tasks in the task-list
349//
350Bool_t MTaskList::Process()
351{
352 //
353 // Check whether there is something which can be processed, otherwise
354 // stop the eventloop.
355 //
356 if (fTasksProcess.GetSize()==0)
357 {
358 *fLog << warn << "Warning: No entries in " << GetDescriptor() << " for Processing." << endl;
359 return kFALSE;
360 }
361
362 //
363 // Reset the ReadyToSave flag.
364 // Reset all containers.
365 //
366 // FIXME: To run a tasklist as a single task in another tasklist we
367 // have to make sure, that the Parameter list isn't reset.
368 //
369 fParList->SetReadyToSave(kFALSE);
370 fParList->Reset();
371
372 //
373 // create the Iterator for the TaskList
374 //
375 TIter Next(&fTasksProcess);
376 MTask *task=NULL;
377
378 //
379 // loop over all tasks for processing
380 //
381 while ( (task=(MTask*)Next()) )
382 {
383 //
384 // if the task has the wrong stream id skip it.
385 //
386 if (GetStreamId() != task->GetStreamId() &&
387 task->GetStreamId() != "All")
388 continue;
389
390 //
391 // if it has the right stream id execute the CallProcess() function
392 // and check what the result of it is.
393 // The CallProcess() function increases the execution counter and
394 // calls the Process() function dependent on the existance and
395 // return value of a filter.
396 //
397 switch (task->CallProcess())
398 {
399 case kTRUE:
400 //
401 // everything was OK: go on with the next task
402 //
403 continue;
404
405 case kFALSE:
406 //
407 // an error occured: stop eventloop
408 //
409 return kFALSE;
410
411 case kCONTINUE:
412 //
413 // something occured: skip the rest of the tasks for this event
414 //
415 return kTRUE;
416
417 default:
418 *fLog << warn << "MTaskList::Process: Unknown return value from MTask::Process()... ignored." << endl;
419 }
420 }
421
422 return kTRUE;
423}
424
425// --------------------------------------------------------------------------
426//
427// do post processing (before eventloop) of all tasks in the task-list
428// only tasks which have successfully been preprocessed are postprocessed.
429//
430Bool_t MTaskList::PostProcess()
431{
432 *fLog << all << "Postprocessing... " << flush;
433
434 //
435 // Reset the ReadyToSave flag.
436 // Reset all containers.
437 //
438 // FIXME: To run a tasklist as a single task in another tasklist we
439 // have to make sure, that the Parameter list isn't reset.
440 //
441 fParList->SetReadyToSave(kFALSE);
442 fParList->Reset();
443
444 //
445 // create the Iterator for the TaskList
446 //
447 TIter Next(fTasks);
448
449 MTask *task=NULL;
450
451 //
452 // loop over all tasks for postprocessing
453 // only tasks which have successfully been preprocessed are postprocessed.
454 //
455 while ( (task=(MTask*)Next()) )
456 {
457 if (!task->CallPostProcess())
458 return kFALSE;
459
460 *fLog << all << task->GetName() << "... " << flush;
461 }
462
463 *fLog << all << endl;
464
465 return kTRUE;
466}
467
468// --------------------------------------------------------------------------
469//
470// Prints the number of times all the tasks in the list has been.
471// For convinience the lvl argument results in a number of spaces at the
472// beginning of the line. So that the structur of a tasklist can be
473// identified. Use MTaskList::PrintStatistics without an argument.
474//
475void MTaskList::PrintStatistics(const Int_t lvl) const
476{
477 if (lvl==0)
478 {
479 *fLog << all << endl;
480 *fLog << "Execution Statistics: " << endl;
481 *fLog << "---------------------" << endl;
482 *fLog << GetDescriptor() << endl;
483 }
484 else
485 {
486 *fLog << setw(lvl) << " " << GetDescriptor() << endl;
487 }
488
489 //
490 // create the Iterator for the TaskList
491 //
492 fTasks->ForEach(MTask, PrintStatistics)(lvl+1);
493
494 if (lvl==0)
495 *fLog << endl;
496}
497
498// --------------------------------------------------------------------------
499void MTaskList::Print(Option_t *t) const
500{
501 *fLog << all << endl;
502 *fLog << GetDescriptor() << endl;
503 *fLog << setfill('-') << setw(strlen(GetDescriptor())) << "" << endl;
504
505 fTasks->Print();
506
507 *fLog << endl;
508}
509
Note: See TracBrowser for help on using the repository browser.