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

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