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

Last change on this file since 1615 was 1542, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 16.7 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 <fstream.h> // ofstream, SavePrimitive
60
61#include <TClass.h>
62#include <TBaseClass.h>
63#include <TOrdCollection.h>
64
65#include "MLog.h"
66#include "MLogManip.h"
67
68#include "MFilter.h"
69#include "MParList.h"
70#include "MInputStreamID.h"
71
72ClassImp(MTaskList);
73
74const TString MTaskList::gsDefName = "MTaskList";
75const TString MTaskList::gsDefTitle = "A list for tasks to be executed";
76
77// --------------------------------------------------------------------------
78//
79// the name for the task list must be the same for all task lists
80// because the task list (at the moment) is identified by exactly
81// this name in the parameter list (by MEvtLoop::SetParList)
82//
83MTaskList::MTaskList(const char *name, const char *title)
84{
85 fName = name ? name : gsDefName.Data();
86 fTitle = title ? title : gsDefTitle.Data();
87
88 fTasks = new TList;
89}
90
91// --------------------------------------------------------------------------
92//
93// CopyConstructor
94// creates a new TaskList and put the contents of an existing
95// TaskList in the new TaskList.
96//
97MTaskList::MTaskList(MTaskList &ts)
98{
99 fTasks->AddAll(ts.fTasks);
100}
101
102// --------------------------------------------------------------------------
103//
104// If the 'IsOwner' bit is set (via SetOwner()) all tasks are deleted
105// by the destructor
106//
107MTaskList::~MTaskList()
108{
109 if (TestBit(kIsOwner))
110 fTasks->SetOwner();
111
112 delete fTasks;
113}
114
115// --------------------------------------------------------------------------
116//
117// If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted
118// by the destructor
119//
120void MTaskList::SetOwner(Bool_t enable)
121{
122 enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
123}
124
125
126// --------------------------------------------------------------------------
127//
128// Set the logging stream for the all tasks in the list and the tasklist
129// itself.
130//
131void MTaskList::SetLogStream(MLog *log)
132{
133 fTasks->ForEach(MTask, SetLogStream)(log);
134 MParContainer::SetLogStream(log);
135}
136
137
138// --------------------------------------------------------------------------
139//
140// schedule task for execution, whether as first task, or after
141// 'where'. 'tType' is the event type which should be processed
142//
143Bool_t MTaskList::AddToList(MTask *task, const char *type, MTask *where)
144{
145 // FIXME: We agreed to put the task into list in an ordered way.
146
147 //
148 // Sanity check
149 //
150 if (!task)
151 return kFALSE;
152
153 //
154 // Get Name of new task
155 //
156 const char *name = task->GetName();
157
158 //
159 // Check if the new task is already existing in the list
160 //
161 const TObject *objn = fTasks->FindObject(name);
162 const TObject *objt = fTasks->FindObject(task);
163
164 if (objn || objt)
165 {
166 //
167 // If the task is already in the list ignore it.
168 //
169 if (objt || objn==task)
170 {
171 *fLog << warn << dbginf << "Warning: Task '" << task->GetName() << ", 0x" << (void*)task;
172 *fLog << "' already existing in '" << GetName() << "'... ignoring." << endl;
173 return kTRUE;
174 }
175
176 //
177 // Otherwise add it to the list, but print a warning message
178 //
179 *fLog << warn << dbginf << "Warning: Task '" << task->GetName();
180 *fLog << "' already existing in '" << GetName() << "'." << endl;
181 *fLog << "You may not be able to get a pointer to this task by name." << endl;
182 }
183
184 if (where)
185 {
186 if (!fTasks->FindObject(where))
187 {
188 *fLog << err << dbginf << "Error: Cannot find task after which the new task should be scheduled!" << endl;
189 return kFALSE;
190 }
191 }
192
193 *fLog << inf << "Adding " << name << " to " << GetName() << " for " << type << "... " << flush;
194
195 task->SetStreamId(type);
196 fTasks->Add(task);
197
198 *fLog << "Done." << endl;
199
200 return kTRUE;
201}
202
203// --------------------------------------------------------------------------
204//
205// Find an object in the list.
206// 'name' is the name of the object you are searching for.
207//
208TObject *MTaskList::FindObject(const char *name) const
209{
210 return fTasks->FindObject(name);
211}
212
213// --------------------------------------------------------------------------
214//
215// check if the object is in the list or not
216//
217TObject *MTaskList::FindObject(const TObject *obj) const
218{
219 return fTasks->FindObject(obj);
220}
221
222// --------------------------------------------------------------------------
223//
224// do reinit of all tasks in the task-list
225//
226Bool_t MTaskList::ReInit(MParList *pList)
227{
228 *fLog << all << "Reinit... " << flush;
229
230 //
231 // create the Iterator over the tasklist
232 //
233 TIter Next(fTasks);
234
235 MTask *task=NULL;
236 //
237 // loop over all tasks for preproccesing
238 //
239 while ((task=(MTask*)Next()))
240 {
241 *fLog << all << task->GetName() << "... " << flush;
242
243 if (!task->ReInit(pList?pList:fParList))
244 {
245 *fLog << err << "ERROR - ReInit if Task " << task->GetDescriptor() << " failed." << endl;
246 return kFALSE;
247 }
248 }
249
250 *fLog << all << endl;
251
252 return kTRUE;
253}
254
255// --------------------------------------------------------------------------
256//
257// removes a task from the list (used in PreProcess).
258// if kIsOwner is set the task is deleted. (see SetOwner())
259//
260void MTaskList::Remove(MTask *task)
261{
262 TObject *obj = fTasks->Remove(task);
263
264 if (TestBit(kIsOwner))
265 delete obj;
266}
267
268// --------------------------------------------------------------------------
269//
270// Check whether this task (or one of it's base classes) overloads
271// MTask::Process. Only if this function is overloaded this task is
272// added to the fTaskProcess-List. This makes the execution of the
273// tasklist a little bit (only a little bit) faster, bacause tasks
274// doing no Processing are not Processed.
275//
276Bool_t MTaskList::CheckClassForProcess(TClass *cls)
277{
278 //
279 // Check whether the class itself overloads the Process function
280 //
281 if (cls->GetName()=="MTask")
282 return kFALSE;
283
284 if (cls->GetMethodAny("Process"))
285 return kTRUE;
286
287 //
288 // If the class itself doesn't overload it check all it's base classes
289 //
290 TBaseClass *base=NULL;
291 TIter NextBase(cls->GetListOfBases());
292 while ((base=(TBaseClass*)NextBase()))
293 {
294 if (CheckClassForProcess(base->GetClassPointer()))
295 return kTRUE;
296 }
297
298 return kFALSE;
299}
300
301// --------------------------------------------------------------------------
302//
303// do pre processing (before eventloop) of all tasks in the task-list
304//
305Bool_t MTaskList::PreProcess(MParList *pList)
306{
307 *fLog << all << "Preprocessing... " << flush;
308
309 fParList = pList;
310
311 fTasksProcess.Clear();
312
313 //
314 // create the Iterator over the tasklist
315 //
316 TIter Next(fTasks);
317
318 MTask *task=NULL;
319
320 //
321 // loop over all tasks for preproccesing
322 //
323 while ((task=(MTask*)Next()))
324 {
325 *fLog << all << task->GetName() << "... " << flush;
326
327 if (CheckClassForProcess(task->IsA()))
328 fTasksProcess.Add(task);
329
330 //
331 // PreProcess the task and check for it's return value.
332 //
333 switch (task->CallPreProcess(fParList))
334 {
335 case kFALSE:
336 return kFALSE;
337
338 case kTRUE:
339 continue;
340
341 case kSKIP:
342 Remove(task);
343 continue;
344 }
345
346 *fLog << err << dbginf << "PreProcess of " << task->GetDescriptor();
347 *fLog << " returned an unknown value... aborting." << endl;
348 return kFALSE;
349 }
350
351 *fLog << all << endl;
352
353 return kTRUE;
354}
355
356// --------------------------------------------------------------------------
357//
358// do the event execution of all tasks in the task-list
359//
360Bool_t MTaskList::Process()
361{
362 //
363 // Check whether there is something which can be processed, otherwise
364 // stop the eventloop.
365 //
366 if (fTasksProcess.GetSize()==0)
367 {
368 *fLog << warn << "Warning: No entries in " << GetDescriptor() << " for Processing." << endl;
369 return kFALSE;
370 }
371
372 //
373 // Reset the ReadyToSave flag.
374 // Reset all containers.
375 //
376 // Make sure, that the parameter list is not reset from a tasklist
377 // running as a task in another tasklist.
378 //
379 const Bool_t noreset = fParList->TestBit(MParList::kDoNotReset);
380 if (!noreset)
381 {
382 fParList->SetReadyToSave(kFALSE);
383 fParList->Reset();
384 fParList->SetBit(MParList::kDoNotReset);
385 }
386
387 //
388 // create the Iterator for the TaskList
389 //
390 TIter Next(&fTasksProcess);
391 MTask *task=NULL;
392
393 //
394 // loop over all tasks for processing
395 //
396 Bool_t rc = kTRUE;
397 while ( (task=(MTask*)Next()) )
398 {
399 //
400 // if the task has the wrong stream id skip it.
401 //
402 if (GetStreamId() != task->GetStreamId() &&
403 task->GetStreamId() != "All")
404 continue;
405
406 //
407 // if it has the right stream id execute the CallProcess() function
408 // and check what the result of it is.
409 // The CallProcess() function increases the execution counter and
410 // calls the Process() function dependent on the existance and
411 // return value of a filter.
412 //
413 switch (task->CallProcess())
414 {
415 case kTRUE:
416 //
417 // everything was OK: go on with the next task
418 //
419 continue;
420
421 case kFALSE:
422 //
423 // an error occured: stop eventloop
424 //
425 rc = kFALSE;
426 break;
427
428 case kCONTINUE:
429 //
430 // something occured: skip the rest of the tasks for this event
431 //
432 rc = kTRUE;
433 break;
434
435 default:
436 *fLog << warn << "MTaskList::Process: Unknown return value from MTask::Process()... ignored." << endl;
437 continue;
438 }
439 break;
440 }
441
442 if (!noreset)
443 fParList->ResetBit(MParList::kDoNotReset);
444
445 return rc;
446}
447
448// --------------------------------------------------------------------------
449//
450// do post processing (before eventloop) of all tasks in the task-list
451// only tasks which have successfully been preprocessed are postprocessed.
452//
453Bool_t MTaskList::PostProcess()
454{
455 *fLog << all << "Postprocessing... " << flush;
456
457 //
458 // Reset the ReadyToSave flag.
459 // Reset all containers.
460 //
461 // FIXME: To run a tasklist as a single task in another tasklist we
462 // have to make sure, that the Parameter list isn't reset.
463 //
464 fParList->SetReadyToSave(kFALSE);
465 fParList->Reset();
466
467 //
468 // create the Iterator for the TaskList
469 //
470 TIter Next(fTasks);
471
472 MTask *task=NULL;
473
474 //
475 // loop over all tasks for postprocessing
476 // only tasks which have successfully been preprocessed are postprocessed.
477 //
478 while ( (task=(MTask*)Next()) )
479 {
480 *fLog << all << task->GetName() << "... " << flush;
481
482 if (!task->CallPostProcess())
483 return kFALSE;
484 }
485
486 *fLog << all << endl;
487
488 return kTRUE;
489}
490
491// --------------------------------------------------------------------------
492//
493// Prints the number of times all the tasks in the list has been.
494// For convinience the lvl argument results in a number of spaces at the
495// beginning of the line. So that the structur of a tasklist can be
496// identified. If a Tasklist or task has filter applied the name of the
497// filter is printer in <>-brackets behind the number of executions.
498// Use MTaskList::PrintStatistics without an argument.
499//
500void MTaskList::PrintStatistics(const Int_t lvl, Bool_t title) const
501{
502 if (lvl==0)
503 {
504 *fLog << all << endl;
505 *fLog << "Execution Statistics: " << endl;
506 *fLog << "---------------------" << endl;
507 *fLog << GetDescriptor();
508 if (GetFilter())
509 *fLog << " <" << GetFilter()->GetName() << ">";
510 if (title)
511 *fLog << "\t" << fTitle;
512 *fLog << endl;
513 }
514 else
515 {
516 *fLog << setw(lvl) << " " << GetDescriptor();
517 if (title)
518 *fLog << "\t" << fTitle;
519 *fLog << endl;
520 }
521
522 //
523 // create the Iterator for the TaskList
524 //
525 fTasks->ForEach(MTask, PrintStatistics)(lvl+1, title);
526
527 if (lvl==0)
528 *fLog << endl;
529}
530
531
532// --------------------------------------------------------------------------
533void MTaskList::Print(Option_t *t) const
534{
535 *fLog << all << endl;
536 *fLog << GetDescriptor() << endl;
537 *fLog << setfill('-') << setw(strlen(GetDescriptor())) << "" << endl;
538
539 fTasks->Print();
540
541 *fLog << endl;
542}
543
544// --------------------------------------------------------------------------
545//
546// Implementation of SavePrimitive. Used to write the call to a constructor
547// to a macro. In the original root implementation it is used to write
548// gui elements to a macro-file.
549//
550void MTaskList::StreamPrimitive(ofstream &out) const
551{
552 out << " MTaskList " << GetUniqueName();
553 if (fName!=gsDefName || fTitle!=gsDefTitle)
554 {
555 out << "(\"" << fName << "\"";
556 if (fTitle!=gsDefTitle)
557 out << ", \"" << fTitle << "\"";
558 out <<")";
559 }
560 out << ";" << endl << endl;
561
562 TIter Next(fTasks);
563
564 MParContainer *cont = NULL;
565 while ((cont=(MParContainer*)Next()))
566 {
567 cont->SavePrimitive(out, "");
568 out << " " << GetUniqueName() << ".AddToList(&";
569 out << cont->GetUniqueName() << ");" << endl << endl;
570 }
571}
572
573void MTaskList::GetNames(TObjArray &arr) const
574{
575 MParContainer::GetNames(arr);
576 fTasks->ForEach(MParContainer, GetNames)(arr);
577}
578
579void MTaskList::SetNames(TObjArray &arr)
580{
581 MParContainer::SetNames(arr);
582 fTasks->ForEach(MParContainer, SetNames)(arr);
583}
584
Note: See TracBrowser for help on using the repository browser.