source: trunk/Mars/mbase/MTaskList.cc@ 20094

Last change on this file since 20094 was 19345, checked in by tbretz, 6 years ago
Improves the behaviour with RecursiveRemove. Strictly speaking this change might only be necessary if a class contains more than one member which is bound to recursive remove. Onth other hand setting all members to NULL which might be affected by RecursiveRemove is not wrong either.
File size: 31.5 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@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2008
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// Remark: The Process function is only executed if the class of your task
46// overloads Process() or if the task itself is a MTask. This
47// means if you have a task without Process() (only PreProcess
48// and PostProcess no time is lost during execution)
49//
50// Warning:
51// Be carefull if you are writing your tasklist
52// (eg. MWriteRootFile("file.root", "MTaskList")) to a file. You may
53// not be able to initialize a new working tasklist from a file if
54// a) Two Paramerer containers with the same names are existing in the
55// MParList.
56// b) You used a container somewhere which is not part of MParList.
57// (eg. You specified a pointer to a MH container in MFillH which is
58// not added to the parameter list.
59//
60/////////////////////////////////////////////////////////////////////////////
61#include "MTaskList.h"
62
63#include <fstream> // ofstream, SavePrimitive
64
65#include <TSystem.h> // gSystem
66#include <TOrdCollection.h> // TOrdCollection
67
68#include "MLog.h"
69#include "MLogManip.h"
70
71#include "MIter.h"
72#include "MFilter.h"
73#include "MParList.h"
74#include "MInputStreamID.h"
75
76#include "MStatusDisplay.h"
77
78ClassImp(MTaskList);
79
80using namespace std;
81
82//#define DEBUG_PROCESS
83#undef DEBUG_PROCESS
84
85const TString MTaskList::gsDefName = "MTaskList";
86const TString MTaskList::gsDefTitle = "A list for tasks to be executed";
87
88// --------------------------------------------------------------------------
89//
90// the name for the task list must be the same for all task lists
91// because the task list (at the moment) is identified by exactly
92// this name in the parameter list (by MEvtLoop::SetParList)
93//
94MTaskList::MTaskList(const char *name, const char *title) : fTasks(0), fParList(0), fNumPasses(0), fNumPass(0)
95{
96 fName = name ? name : gsDefName.Data();
97 fTitle = title ? title : gsDefTitle.Data();
98
99 fTasks = new TList;
100
101 gROOT->GetListOfCleanups()->Add(fTasks);
102 gROOT->GetListOfCleanups()->Add(&fTasksProcess);
103 fTasks->SetBit(kMustCleanup);
104 fTasksProcess.SetBit(kMustCleanup);
105}
106
107// --------------------------------------------------------------------------
108//
109// CopyConstructor
110// creates a new TaskList and put the contents of an existing
111// TaskList in the new TaskList.
112//
113MTaskList::MTaskList(const MTaskList &ts) : MTask(), fNumPasses(ts.fNumPasses)
114{
115 fTasks->AddAll(ts.fTasks);
116}
117
118// --------------------------------------------------------------------------
119//
120// If the 'IsOwner' bit is set (via SetOwner()) all tasks are deleted
121// by the destructor
122//
123MTaskList::~MTaskList()
124{
125 if (TestBit(kIsOwner))
126 fTasks->SetOwner();
127
128 delete fTasks;
129 fTasks = 0;
130}
131
132// --------------------------------------------------------------------------
133//
134// If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted
135// by the destructor
136//
137void MTaskList::SetOwner(Bool_t enable)
138{
139 enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
140}
141
142
143// --------------------------------------------------------------------------
144//
145// Set the logging stream for the all tasks in the list and the tasklist
146// itself.
147//
148void MTaskList::SetLogStream(MLog *log)
149{
150 fTasks->R__FOR_EACH(MTask, SetLogStream)(log);
151 MTask::SetLogStream(log);
152}
153
154// --------------------------------------------------------------------------
155//
156// Set the display for the all tasks in the list and the tasklist itself.
157//
158void MTaskList::SetDisplay(MStatusDisplay *d)
159{
160 fTasks->R__FOR_EACH(MTask, SetDisplay)(d);
161 MTask::SetDisplay(d);
162}
163
164void MTaskList::SetAccelerator(Byte_t acc)
165{
166 fTasks->R__FOR_EACH(MTask, SetAccelerator)(acc);
167 MTask::SetAccelerator(acc);
168}
169
170// --------------------------------------------------------------------------
171//
172// Set the serial number for the all tasks in the list and the tasklist
173// itself.
174//
175void MTaskList::SetSerialNumber(Byte_t num)
176{
177 fTasks->R__FOR_EACH(MTask, SetSerialNumber)(num);
178 MTask::SetSerialNumber(num);
179}
180
181Bool_t MTaskList::CheckAddToList(MTask *task, /*const char *type,*/ const MTask *where) const
182{
183 //
184 // Sanity check
185 //
186 if (!task)
187 {
188 *fLog << err << "ERROR - task argument=NULL." << endl;
189 return kFALSE;
190 }
191
192 //
193 // Get Name of new task
194 //
195 const char *name = task->GetName();
196
197 //
198 // Check if the new task is already existing in the list
199 //
200 const TObject *objn = fTasks->FindObject(name);
201 const TObject *objt = fTasks->FindObject(task);
202
203 if (objn || objt)
204 {
205 //
206 // If the task is already in the list ignore it.
207 //
208 if (objt || objn==task)
209 {
210 *fLog << warn << dbginf << "Warning: Task '" << task->GetName() << ", 0x" << (void*)task;
211 *fLog << "' already existing in '" << GetName() << "'... ignoring." << endl;
212 return kTRUE;
213 }
214
215 //
216 // Otherwise add it to the list, but print a warning message
217 //
218 *fLog << warn << dbginf << "Warning: Task '" << task->GetName();
219 *fLog << "' already existing in '" << GetName() << "'." << endl;
220 *fLog << "You may not be able to get a pointer to this task by name." << endl;
221 }
222
223 if (!where)
224 return kTRUE;
225
226 if (fTasks->FindObject(where))
227 return kTRUE;
228
229 *fLog << err << dbginf << "Error: Cannot find task after which the new task should be scheduled!" << endl;
230 return kFALSE;
231}
232
233
234// --------------------------------------------------------------------------
235//
236// schedule task for execution, before 'where'.
237// 'type' is the event type which should be processed
238//
239Bool_t MTaskList::AddToListBefore(MTask *task, const MTask *where, const char *type)
240{
241 if (task==this)
242 {
243 *fLog << warn << "WARNING - You cannot add a tasklist to itself. This" << endl;
244 *fLog << " would create infinite recursions...ignored." << endl;
245 return kFALSE;
246
247 }
248
249 // FIXME: We agreed to put the task into list in an ordered way.
250 if (!CheckAddToList(task, /*type,*/ where))
251 return kFALSE;
252
253 const TString stream = type ? (TString)type : task->GetStreamId();
254
255 *fLog << inf3 << "Adding " << task->GetName() << " to " << GetName() << " for " << stream << "... " << flush;
256 task->SetStreamId(stream);
257 task->SetBit(kMustCleanup);
258 fTasks->AddBefore((TObject*)where, task);
259 *fLog << "done." << endl;
260
261 return kTRUE;
262}
263
264// --------------------------------------------------------------------------
265//
266// schedule task for execution, after 'where'.
267// 'type' is the event type which should be processed
268//
269Bool_t MTaskList::AddToListAfter(MTask *task, const MTask *where, const char *type)
270{
271 if (task==this)
272 {
273 *fLog << warn << "WARNING - You cannot add a tasklist to itself. This" << endl;
274 *fLog << " would create infinite recursions...ignored." << endl;
275 return kFALSE;
276
277 }
278
279 // FIXME: We agreed to put the task into list in an ordered way.
280 if (!CheckAddToList(task, /*type,*/ where))
281 return kFALSE;
282
283 const TString stream = type ? (TString)type : task->GetStreamId();
284
285 *fLog << inf3 << "Adding " << task->GetName() << " to " << GetName() << " for " << stream << "... " << flush;
286 task->SetStreamId(stream);
287 task->SetBit(kMustCleanup);
288 fTasks->AddAfter((TObject*)where, task);
289 *fLog << "done." << endl;
290
291 return kTRUE;
292}
293
294// --------------------------------------------------------------------------
295//
296// schedule task for execution, 'type' is the event type which should
297// be processed
298//
299Bool_t MTaskList::AddToList(MTask *task, const char *type)
300{
301 if (task==this)
302 {
303 *fLog << warn << "WARNING - You cannot add a tasklist to itself. This" << endl;
304 *fLog << " would create infinite recursions...ignored." << endl;
305 return kFALSE;
306
307 }
308
309 // FIXME: We agreed to put the task into list in an ordered way.
310 if (!CheckAddToList(task/*, type*/))
311 return kFALSE;
312
313 const TString stream = type ? (TString)type : task->GetStreamId();
314
315 *fLog << inf3 << "Adding " << task->GetName() << " to " << GetName() << " for " << stream << "... " << flush;
316 task->SetStreamId(stream);
317 task->SetBit(kMustCleanup);
318 fTasks->Add(task);
319 *fLog << "done." << endl;
320
321 return kTRUE;
322}
323
324// --------------------------------------------------------------------------
325//
326// Add all objects in list to the tasklist. If some of them do not
327// inherit from MTask return kFALSE, also if AddToList returns an error
328// for one of the tasks
329//
330Bool_t MTaskList::AddToList(const TList &list, const char *tType)
331{
332 TIter Next(&list);
333 TObject *obj=0;
334 while ((obj=Next()))
335 {
336 if (!obj->InheritsFrom(MTask::Class()))
337 {
338 *fLog << err << "ERROR - Object " << obj->GetName() << " doesn't inherit from MTask..." << endl;
339 return kFALSE;
340 }
341
342 if (!AddToList(static_cast<MTask*>(obj), tType))
343 return kFALSE;
344 }
345 return kTRUE;
346}
347
348// --------------------------------------------------------------------------
349//
350// Add all objects in list to the tasklist after task where. If some of
351// them do not inherit from MTask return kFALSE, also if AddToListAfter
352// returns an error for one of the tasks
353//
354Bool_t MTaskList::AddToListAfter(const TList &list, const MTask *where, const char *tType)
355{
356 TIter Next(&list);
357 TObject *obj=0;
358 while ((obj=Next()))
359 {
360 if (!obj->InheritsFrom(MTask::Class()))
361 {
362 *fLog << err << "ERROR - Object " << obj->GetName() << " doesn't inherit from MTask..." << endl;
363 return kFALSE;
364 }
365
366 if (!AddToListAfter(static_cast<MTask*>(obj), where, tType))
367 return kFALSE;
368
369 where = static_cast<MTask*>(obj);
370 }
371 return kTRUE;
372}
373
374// --------------------------------------------------------------------------
375//
376// Add all objects in list to the tasklist before task where. If some of
377// them do not inherit from MTask return kFALSE, also if AddToListBefore
378// returns an error for one of the tasks
379//
380Bool_t MTaskList::AddToListBefore(const TList &list, const MTask *where, const char *tType)
381{
382 TIter Next(&list);
383 TObject *obj=0;
384 while ((obj=Next()))
385 {
386 if (!obj->InheritsFrom(MTask::Class()))
387 {
388 *fLog << err << "ERROR - Object " << obj->GetName() << " doesn't inherit from MTask..." << endl;
389 return kFALSE;
390 }
391
392 if (!AddToListBefore(static_cast<MTask*>(obj), where, tType))
393 return kFALSE;
394 }
395 return kTRUE;
396}
397
398// --------------------------------------------------------------------------
399//
400// Find an object in the list.
401// 'name' is the name of the object you are searching for.
402//
403TObject *MTaskList::FindObject(const char *name) const
404{
405 return fTasks->FindObject(name);
406}
407
408// --------------------------------------------------------------------------
409//
410// check if the object is in the list or not
411//
412TObject *MTaskList::FindObject(const TObject *obj) const
413{
414 return fTasks->FindObject(obj);
415}
416
417// --------------------------------------------------------------------------
418//
419// find recursively a tasklist which contains a task with name task
420//
421MTaskList *MTaskList::FindTaskList(const char *task)
422{
423 TIter Next(fTasks);
424 TObject *o = 0;
425 while ((o=Next()))
426 {
427 if (strcmp(o->GetName(), task)==0)
428 return this;
429
430 MTaskList *l = dynamic_cast<MTaskList*>(o);
431 if (!l)
432 continue;
433
434 if ((l=l->FindTaskList(task)))
435 return l;
436 }
437 return 0;
438}
439
440// --------------------------------------------------------------------------
441//
442// find recursively a tasklist which contains a task task
443//
444MTaskList *MTaskList::FindTaskList(const MTask *task)
445{
446 TIter Next(fTasks);
447 TObject *o = 0;
448 while ((o=Next()))
449 {
450 if (o==task)
451 return this;
452
453 MTaskList *l = dynamic_cast<MTaskList*>(o);
454 if (!l)
455 continue;
456
457 if ((l=l->FindTaskList(task)))
458 return l;
459 }
460
461 return 0;
462}
463
464// --------------------------------------------------------------------------
465//
466// removes a task from the list (used in PreProcess).
467// if kIsOwner is set the task is deleted. (see SetOwner())
468//
469void MTaskList::Remove(MTask *task)
470{
471 if (!task)
472 return;
473
474 // First remove it from the list(s) so that a later RecursiveRemove
475 // cannot fint the task again
476 TObject *obj = fTasks->Remove(task);
477
478 // Now do a recursive remove on all other tasks.
479 fTasks->RecursiveRemove(task);
480
481 if (obj && TestBit(kIsOwner))
482 delete obj;
483}
484
485// --------------------------------------------------------------------------
486//
487// Call MTask::RecursiveRemove
488// Call fTasks->RecursiveRemove
489//
490void MTaskList::RecursiveRemove(TObject *obj)
491{
492 MTask::RecursiveRemove(obj);
493
494 if (obj==fTasks)
495 fTasks=NULL;
496
497 if (fTasks)
498 {
499 fTasks->RecursiveRemove(obj);
500
501 // In theory this call is obsolete
502 fTasksProcess.RecursiveRemove(obj);
503 }
504}
505
506// --------------------------------------------------------------------------
507//
508// do pre processing (before eventloop) of all tasks in the task-list
509// Only if a task overwrites the Process function the task is
510// added to the fTaskProcess-List. This makes the execution of the
511// tasklist a little bit (only a little bit) faster, bacause tasks
512// doing no Processing are not Processed.
513//
514Int_t MTaskList::PreProcess(MParList *pList)
515{
516 *fLog << all << "Preprocessing... " << flush;
517 if (fDisplay)
518 {
519 // Set status lines
520 fDisplay->SetStatusLine1("PreProcessing...");
521 fDisplay->SetStatusLine2("");
522 }
523
524 fParList = pList;
525
526 //
527 // Make sure, that the ReadyToSave flag is not reset from a tasklist
528 // running as a task in another tasklist.
529 //
530 const Bool_t noreset = fParList->TestBit(MParList::kDoNotReset);
531 if (!noreset)
532 fParList->SetBit(MParList::kDoNotReset);
533
534 //
535 // create the Iterator over the tasklist
536 //
537 TIter Next(fTasks);
538
539 MTask *task=NULL;
540
541 //
542 // loop over all tasks for preproccesing
543 //
544 while ((task=(MTask*)Next()))
545 {
546 //
547 // PreProcess the task and check for it's return value.
548 //
549 switch (task->CallPreProcess(fParList))
550 {
551 case kFALSE:
552 return kFALSE;
553
554 case kTRUE:
555 // Handle GUI events (display changes, mouse clicks)
556 if (fDisplay)
557 gSystem->ProcessEvents();
558 continue;
559
560 case kSKIP:
561 Remove(task);
562 continue;
563 }
564
565 *fLog << err << dbginf << "PreProcess of " << task->GetDescriptor();
566 *fLog << " returned an unknown value... aborting." << endl;
567 return kFALSE;
568 }
569
570 *fLog << all << endl;
571
572 //
573 // Reset the ReadyToSave flag.
574 //
575 if (!noreset)
576 {
577 fParList->SetReadyToSave(kFALSE);
578 fParList->ResetBit(MParList::kDoNotReset);
579 }
580
581 //
582 // loop over all tasks to fill fTasksProcess
583 //
584 Next.Reset();
585 fTasksProcess.Clear();
586 while ((task=(MTask*)Next()))
587 if (task->IsA()==MTask::Class() || task->Overwrites("Process"))
588 fTasksProcess.Add(task);
589
590 return kTRUE;
591}
592
593// --------------------------------------------------------------------------
594//
595// do reinit of all tasks in the task-list
596//
597Bool_t MTaskList::ReInit(MParList *pList)
598{
599 *fLog << all << "Reinit... " << flush;
600
601 if (!pList)
602 pList = fParList;
603
604 //
605 // Make sure, that the ReadyToSave flag is not reset from a tasklist
606 // running as a task in another tasklist.
607 //
608 const Bool_t noreset = pList->TestBit(MParList::kDoNotReset);
609 if (!noreset)
610 pList->SetBit(MParList::kDoNotReset);
611
612 //
613 // create the Iterator over the tasklist
614 //
615 TIter Next(fTasks);
616
617 MTask *task=NULL;
618
619 //
620 // loop over all tasks for reinitialization
621 //
622 while ((task=(MTask*)Next()))
623 {
624 // Supress output if not necessary
625 if (!task->Overwrites("ReInit"))
626 continue;
627
628 *fLog << all << task->GetName() << "... " << flush;
629
630 if (!task->ReInit(pList/*?pList:fParList*/))
631 {
632 *fLog << err << "ERROR - ReInit of Task '" << task->GetDescriptor() << "' failed." << endl;
633 return kFALSE;
634 }
635 }
636
637 *fLog << all << endl;
638
639 //
640 // Reset the ReadyToSave flag.
641 //
642 if (!noreset)
643 {
644 pList->SetReadyToSave(kFALSE);
645 pList->ResetBit(MParList::kDoNotReset);
646 }
647
648 return kTRUE;
649}
650
651Int_t MTaskList::ProcessTaskList()
652{
653 //
654 // create the Iterator for the TaskList
655 //
656 TIter Next(&fTasksProcess);
657 MTask *task=NULL;
658
659#ifdef DEBUG_PROCESS
660 *fLog << all << "ProcessTaskList - " << GetDescriptor() << " - start." << endl;
661#endif
662
663 //
664 // loop over all tasks for processing
665 //
666 Int_t rc = kTRUE;
667 while ( (task=(MTask*)Next()) )
668 {
669#ifdef DEBUG_PROCESS
670 *fLog << all << "Process - " << (void*)task << " " << flush;
671 *fLog << task->GetDescriptor() << "... " << flush;
672#endif
673 //
674 // if the task has the wrong stream id skip it.
675 //
676 if (GetStreamId() != task->GetStreamId() &&
677 task->GetStreamId() != "All")
678 continue;
679
680 //
681 // if it has the right stream id execute the CallProcess() function
682 // and check what the result of it is.
683 // The CallProcess() function increases the execution counter and
684 // calls the Process() function dependent on the existance and
685 // return value of a filter.
686 //
687 switch (task->CallProcess())
688 {
689 case kTRUE:
690 //
691 // everything was OK: go on with the next task
692 //
693#ifdef DEBUG_PROCESS
694 *fLog << "true." << endl;
695#endif
696 continue;
697
698 case kFALSE:
699 //
700 // an error occured: stop eventloop
701 //
702 rc = kFALSE;
703 *fLog << inf << task->GetDescriptor() << " has stopped execution of " << GetDescriptor() << "." << endl;
704 break;
705
706 case kERROR:
707 //
708 // an error occured: stop eventloop and return: failed
709 //
710 *fLog << err << "Fatal error occured while Process() of " << task->GetDescriptor() << "... stopped." << endl;
711 rc = kERROR;
712 break;
713
714 case kCONTINUE:
715 //
716 // something occured: skip the rest of the tasks for this event
717 //
718#ifdef DEBUG_PROCESS
719 *fLog << "continue." << endl;
720#endif
721 rc = kCONTINUE;
722 break;
723
724 default:
725 *fLog << err << dbginf << "Unknown return value from MTask::Process()... stopped." << endl;
726 rc = kERROR;
727 break;
728 }
729 break;
730 }
731
732#ifdef DEBUG_PROCESS
733 *fLog << all << "ProcessTaskList - " << GetDescriptor() << " - done." << endl;
734#endif
735
736 return rc;
737}
738
739// --------------------------------------------------------------------------
740//
741// do the event execution of all tasks in the task-list.
742//
743// If a task returns kCONTINUE, kCONTINUE is propagated if the
744// number of passes==0, otherwise kTRUE is returned instead.
745//
746Int_t MTaskList::Process()
747{
748 //
749 // Check whether there is something which can be processed, otherwise
750 // stop the eventloop.
751 //
752 if (fTasksProcess.GetSize()==0)
753 {
754 *fLog << warn << "Warning: No entries in " << GetDescriptor() << " for Processing." << endl;
755 return kFALSE;
756 }
757
758 //
759 // Reset the ReadyToSave flag.
760 // Reset all containers.
761 //
762 // Make sure, that the parameter list is not reset from a tasklist
763 // running as a task in another tasklist.
764 //
765 const Bool_t noreset = fParList->TestBit(MParList::kIsProcessing);
766 if (!noreset)
767 {
768 fParList->SetBit(MParList::kIsProcessing);
769 if (!HasAccelerator(kAccDontReset))
770 fParList->Reset();
771 }
772
773 // Initialize storage variable for the return code
774 Int_t rc = kTRUE;
775
776 // Execute the task list at least once
777 const UInt_t cnt = fNumPasses==0 ? 1 : fNumPasses;
778 for (fNumPass=0; fNumPass<cnt; fNumPass++)
779 {
780 // Execute the tasklist once
781 rc = ProcessTaskList();
782 // In cae of error or a stop-request leave loop
783 if (rc==kERROR || rc==kFALSE)
784 break;
785 }
786
787 // Reset to the default
788 if (!noreset)
789 {
790 fParList->SetReadyToSave(kFALSE);
791 fParList->ResetBit(MParList::kIsProcessing);
792 }
793
794 // If the number of passes==0 <default> propagete kCONTINUE
795 if (rc==kCONTINUE)
796 return fNumPasses==0 ? kCONTINUE : kTRUE;
797
798 // Return return code
799 return rc;
800}
801
802// --------------------------------------------------------------------------
803//
804// do post processing (before eventloop) of all tasks in the task-list
805// only tasks which have successfully been preprocessed are postprocessed.
806//
807Int_t MTaskList::PostProcess()
808{
809 *fLog << all << "Postprocessing... " << flush;
810 if (fDisplay)
811 {
812 // Set status lines
813 fDisplay->SetStatusLine1("PostProcessing...");
814 fDisplay->SetStatusLine2("");
815 }
816
817 //
818 // Make sure, that the ReadyToSave flag is not reset from a tasklist
819 // running as a task in another tasklist.
820 //
821 const Bool_t noreset = fParList->TestBit(MParList::kDoNotReset);
822 if (!noreset)
823 {
824 fParList->SetBit(MParList::kDoNotReset);
825 fParList->Reset();
826 }
827
828 //
829 // create the Iterator for the TaskList
830 //
831 TIter Next(fTasks);
832
833 MTask *task=NULL;
834
835 //
836 // loop over all tasks for postprocessing
837 // only tasks which have successfully been preprocessed are postprocessed.
838 //
839 while ( (task=(MTask*)Next()) )
840 {
841 if (!task->CallPostProcess())
842 return kFALSE;
843
844 // Handle GUI events (display changes, mouse clicks)
845 if (fDisplay)
846 gSystem->ProcessEvents();
847 }
848
849 *fLog << all << endl;
850
851 //
852 // Reset the ReadyToSave flag.
853 //
854 if (!noreset)
855 {
856 fParList->SetReadyToSave(kFALSE);
857 fParList->ResetBit(MParList::kDoNotReset);
858 }
859
860 return kTRUE;
861}
862
863// --------------------------------------------------------------------------
864//
865// Prints the number of times all the tasks in the list has been.
866// For convinience the lvl argument results in a number of spaces at the
867// beginning of the line. So that the structur of a tasklist can be
868// identified. If a Tasklist or task has filter applied the name of the
869// filter is printer in <>-brackets behind the number of executions.
870// Use MTaskList::PrintStatistics without an argument.
871//
872void MTaskList::PrintStatistics(const Int_t lvl, Bool_t title, Double_t time) const
873{
874 if (lvl==0)
875 {
876 *fLog << all << underline << "Process execution Statistics:" << endl;
877 *fLog << GetDescriptor();
878 if (GetFilter())
879 *fLog << " <" << GetFilter()->GetName() << ">";
880 if (title)
881 *fLog << "\t" << fTitle;
882 if (time>=0)
883 *fLog << Form(" %5.1f", GetCpuTime()/time*100) << "%";
884 else
885 *fLog << " 100.0%";
886 *fLog << endl;
887 }
888 else
889 MTask::PrintStatistics(lvl, title, time);
890
891 //
892 // create the Iterator for the TaskList
893 //
894 fTasks->R__FOR_EACH(MTask, PrintStatistics)(lvl+1, title, GetCpuTime());
895
896 if (lvl==0)
897 *fLog << endl;
898}
899
900// --------------------------------------------------------------------------
901//
902// Call 'Print()' of all tasks
903//
904void MTaskList::Print(Option_t *) const
905{
906 *fLog << all << underline << GetDescriptor() << ":" << endl;
907
908 fTasks->Print();
909
910 *fLog << endl;
911}
912
913// --------------------------------------------------------------------------
914//
915// Implementation of SavePrimitive. Used to write the call to a constructor
916// to a macro. In the original root implementation it is used to write
917// gui elements to a macro-file.
918//
919void MTaskList::StreamPrimitive(ostream &out) const
920{
921 out << " MTaskList " << GetUniqueName();
922 if (fName!=gsDefName || fTitle!=gsDefTitle)
923 {
924 out << "(\"" << fName << "\"";
925 if (fTitle!=gsDefTitle)
926 out << ", \"" << fTitle << "\"";
927 out <<")";
928 }
929 out << ";" << endl << endl;
930
931 MIter Next(fTasks);
932
933 MParContainer *cont = NULL;
934 while ((cont=Next()))
935 {
936 cont->SavePrimitive(out, "");
937 out << " " << GetUniqueName() << ".AddToList(&";
938 out << cont->GetUniqueName() << ");" << endl << endl;
939 }
940}
941
942void MTaskList::GetNames(TObjArray &arr) const
943{
944 MParContainer::GetNames(arr);
945 fTasks->R__FOR_EACH(MParContainer, GetNames)(arr);
946}
947
948void MTaskList::SetNames(TObjArray &arr)
949{
950 MParContainer::SetNames(arr);
951 fTasks->R__FOR_EACH(MParContainer, SetNames)(arr);
952}
953
954// --------------------------------------------------------------------------
955//
956// Read the contents/setup of a parameter container/task from a TEnv
957// instance (steering card/setup file).
958// The key to search for in the file should be of the syntax:
959// prefix.vname
960// While vname is a name which is specific for a single setup date
961// (variable) of this container and prefix is something like:
962// evtloopname.name
963// While name is the name of the containers/tasks in the parlist/tasklist
964//
965// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
966// Job4.MImgCleanStd.CleaningLevel2: 2.5
967//
968// If this cannot be found the next step is to search for
969// MImgCleanStd.CleaningLevel1: 3.0
970// And if this doesn't exist, too, we should search for:
971// CleaningLevel1: 3.0
972//
973// Warning: The programmer is responsible for the names to be unique in
974// all Mars classes.
975//
976Int_t MTaskList::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
977{
978 if (print)
979 *fLog << all << "MTaskList::ReadEnv: " << prefix << " (" << (int)print << ")" << endl;
980
981 MParContainer *cont = NULL;
982
983 MIter Next(fTasks);
984 while ((cont=Next()))
985 {
986 if (cont->InheritsFrom("MTaskList"))
987 {
988 if (cont->ReadEnv(env, prefix, print)==kERROR)
989 return kERROR;
990 continue;
991 }
992
993 if (cont->TestEnv(env, prefix, print)==kERROR)
994 return kERROR;
995 }
996
997 return kTRUE;
998}
999
1000// --------------------------------------------------------------------------
1001//
1002// Write the contents/setup of a parameter container/task to a TEnv
1003// instance (steering card/setup file).
1004// The key to search for in the file should be of the syntax:
1005// prefix.vname
1006// While vname is a name which is specific for a single setup date
1007// (variable) of this container and prefix is something like:
1008// evtloopname.name
1009// While name is the name of the containers/tasks in the parlist/tasklist
1010//
1011// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
1012// Job4.MImgCleanStd.CleaningLevel2: 2.5
1013//
1014// If this cannot be found the next step is to search for
1015// MImgCleanStd.CleaningLevel1: 3.0
1016// And if this doesn't exist, too, we should search for:
1017// CleaningLevel1: 3.0
1018//
1019// Warning: The programmer is responsible for the names to be unique in
1020// all Mars classes.
1021//
1022Bool_t MTaskList::WriteEnv(TEnv &env, TString prefix, Bool_t print) const
1023{
1024 MParContainer *cont = NULL;
1025
1026 MIter Next(fTasks);
1027 while ((cont=Next()))
1028 if (!cont->WriteEnv(env, prefix, print))
1029 return kFALSE;
1030 return kTRUE;
1031}
1032
1033// --------------------------------------------------------------------------
1034//
1035// Removes a task from the tasklist. Returns kFALSE if the object was not
1036// found in the list.
1037//
1038Bool_t MTaskList::RemoveFromList(MTask *task)
1039{
1040 TObject *obj = fTasks->Remove(task);
1041
1042 //
1043 // If the task was found in the list try to remove it from the second
1044 // list, too.
1045 //
1046 if (obj)
1047 fTasksProcess.Remove(task);
1048
1049 return obj ? kTRUE : kFALSE;
1050
1051}
1052
1053// --------------------------------------------------------------------------
1054//
1055// Removes all task of the TList from the tasklist. Returns kFALSE if any
1056// of the objects was not an MTask or not found in the list.
1057//
1058Bool_t MTaskList::RemoveFromList(const TList &list)
1059{
1060 Bool_t rc = kTRUE;
1061
1062 TIter Next(&list);
1063 TObject *obj=0;
1064 while ((obj=Next()))
1065 {
1066 if (!obj->InheritsFrom(MTask::Class()))
1067 {
1068 *fLog << err << "ERROR - Object " << obj->GetName() << " doesn't inherit from MTask..." << endl;
1069 rc = kFALSE;
1070 continue;
1071 }
1072
1073 if (!RemoveFromList(static_cast<MTask*>(obj)))
1074 rc = kFALSE;
1075 }
1076 return rc;
1077}
1078
1079// --------------------------------------------------------------------------
1080//
1081// Find an object with the same name in the list and replace it with
1082// the new one. If the kIsOwner flag is set and the object was not
1083// created automatically, the object is deleted.
1084//
1085Bool_t MTaskList::Replace(MTask *task)
1086{
1087 //
1088 // check if the object (you want to add) exists
1089 //
1090 if (!task)
1091 return kFALSE;
1092
1093 if (task==this)
1094 {
1095 *fLog << warn << "WARNING - You cannot add a tasklist to itself. This" << endl;
1096 *fLog << " would create infinite recursions...ignored." << endl;
1097 return kFALSE;
1098
1099 }
1100
1101 MTask *obj = (MTask*)FindObject(task->GetName());
1102 if (!obj)
1103 {
1104 *fLog << warn << "No object with the same name '";
1105 *fLog << task->GetName() << "' in list... adding." << endl;
1106 return AddToList(task);
1107 }
1108
1109 if (task==obj)
1110 return kTRUE;
1111
1112 *fLog << inf2 << "Replacing " << task->GetName() << " in " << GetName() << " for " << obj->GetStreamId() << "... " << flush;
1113 task->SetStreamId(obj->GetStreamId());
1114 task->SetBit(kMustCleanup);
1115 fTasks->AddAfter((TObject*)obj, task);
1116 *fLog << "done." << endl;
1117
1118 RemoveFromList(obj);
1119
1120 if (TestBit(kIsOwner))
1121 delete obj;
1122
1123 //*fLog << inf << "MTask '" << task->GetName() << "' found and replaced..." << endl;
1124
1125 return kTRUE;
1126}
1127
1128// --------------------------------------------------------------------------
1129//
1130// Can be used to create an iterator over all tasks, eg:
1131// MTaskList tlist;
1132// TIter Next(tlist); // Be aware: Use a object here rather than a pointer!
1133// TObject *o=0;
1134// while ((o=Next()))
1135// {
1136// [...]
1137// }
1138//
1139MTaskList::operator TIterator*() const
1140{
1141 return new TListIter(fTasks);
1142}
Note: See TracBrowser for help on using the repository browser.