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

Last change on this file since 8785 was 8744, checked in by tbretz, 17 years ago
*** empty log message ***
File size: 31.3 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-2007
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 if (FindObject(task))
423 return this;
424
425 TIter Next(fTasks);
426 TObject *o = 0;
427 while ((o=Next()))
428 {
429 MTaskList *l = dynamic_cast<MTaskList*>(o);
430 if (!l)
431 continue;
432
433 if (l->FindObject(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 if (FindObject(task))
446 return this;
447
448 TIter Next(fTasks);
449 TObject *o = 0;
450 while ((o=Next()))
451 {
452 MTaskList *l = dynamic_cast<MTaskList*>(o);
453 if (!l)
454 continue;
455
456 if (l->FindObject(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->OverwritesProcess())
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 *fLog << all << task->GetName() << "... " << flush;
624
625 if (!task->ReInit(pList/*?pList:fParList*/))
626 {
627 *fLog << err << "ERROR - ReInit of Task '" << task->GetDescriptor() << "' failed." << endl;
628 return kFALSE;
629 }
630 }
631
632 *fLog << all << endl;
633
634 //
635 // Reset the ReadyToSave flag.
636 //
637 if (!noreset)
638 {
639 pList->SetReadyToSave(kFALSE);
640 pList->ResetBit(MParList::kDoNotReset);
641 }
642
643 return kTRUE;
644}
645
646Int_t MTaskList::ProcessTaskList()
647{
648 //
649 // create the Iterator for the TaskList
650 //
651 TIter Next(&fTasksProcess);
652 MTask *task=NULL;
653
654#ifdef DEBUG_PROCESS
655 *fLog << all << "ProcessTaskList - " << GetDescriptor() << " - start." << endl;
656#endif
657
658 //
659 // loop over all tasks for processing
660 //
661 Int_t rc = kTRUE;
662 while ( (task=(MTask*)Next()) )
663 {
664#ifdef DEBUG_PROCESS
665 *fLog << all << "Process - " << (void*)task << " " << flush;
666 *fLog << task->GetDescriptor() << "... " << flush;
667#endif
668 //
669 // if the task has the wrong stream id skip it.
670 //
671 if (GetStreamId() != task->GetStreamId() &&
672 task->GetStreamId() != "All")
673 continue;
674
675 //
676 // if it has the right stream id execute the CallProcess() function
677 // and check what the result of it is.
678 // The CallProcess() function increases the execution counter and
679 // calls the Process() function dependent on the existance and
680 // return value of a filter.
681 //
682 switch (task->CallProcess())
683 {
684 case kTRUE:
685 //
686 // everything was OK: go on with the next task
687 //
688#ifdef DEBUG_PROCESS
689 *fLog << "true." << endl;
690#endif
691 continue;
692
693 case kFALSE:
694 //
695 // an error occured: stop eventloop
696 //
697 rc = kFALSE;
698 *fLog << inf << task->GetDescriptor() << " has stopped execution of " << GetDescriptor() << "." << endl;
699 break;
700
701 case kERROR:
702 //
703 // an error occured: stop eventloop and return: failed
704 //
705 *fLog << err << "Fatal error occured while Process() of " << task->GetDescriptor() << "... stopped." << endl;
706 rc = kERROR;
707 break;
708
709 case kCONTINUE:
710 //
711 // something occured: skip the rest of the tasks for this event
712 //
713#ifdef DEBUG_PROCESS
714 *fLog << "continue." << endl;
715#endif
716 rc = kCONTINUE;
717 break;
718
719 default:
720 *fLog << warn << dbginf << "Unknown return value from MTask::Process()... ignored." << endl;
721 continue;
722 }
723 break;
724 }
725
726#ifdef DEBUG_PROCESS
727 *fLog << all << "ProcessTaskList - " << GetDescriptor() << " - done." << endl;
728#endif
729
730 return rc;
731}
732
733// --------------------------------------------------------------------------
734//
735// do the event execution of all tasks in the task-list.
736//
737// If a task returns kCONTINUE, kCONTINUE is propagated if the
738// number of passes==0, otherwise kTRUE is returned instead.
739//
740Int_t MTaskList::Process()
741{
742 //
743 // Check whether there is something which can be processed, otherwise
744 // stop the eventloop.
745 //
746 if (fTasksProcess.GetSize()==0)
747 {
748 *fLog << warn << "Warning: No entries in " << GetDescriptor() << " for Processing." << endl;
749 return kFALSE;
750 }
751
752 //
753 // Reset the ReadyToSave flag.
754 // Reset all containers.
755 //
756 // Make sure, that the parameter list is not reset from a tasklist
757 // running as a task in another tasklist.
758 //
759 const Bool_t noreset = fParList->TestBit(MParList::kIsProcessing);
760 if (!noreset)
761 {
762 fParList->SetBit(MParList::kIsProcessing);
763 if (!HasAccelerator(kAccDontReset))
764 fParList->Reset();
765 }
766
767 // Initialize storage variable for the return code
768 Int_t rc = kTRUE;
769
770 // Execute the task list at least once
771 const UInt_t cnt = fNumPasses==0 ? 1 : fNumPasses;
772 for (fNumPass=0; fNumPass<cnt; fNumPass++)
773 {
774 // Execute the tasklist once
775 rc = ProcessTaskList();
776 // In cae of error or a stop-request leave loop
777 if (rc==kERROR || rc==kFALSE)
778 break;
779 }
780
781 // Reset to the default
782 if (!noreset)
783 {
784 fParList->SetReadyToSave(kFALSE);
785 fParList->ResetBit(MParList::kIsProcessing);
786 }
787
788 // If the number of passes==0 <default> propagete kCONTINUE
789 if (rc==kCONTINUE)
790 return fNumPasses==0 ? kCONTINUE : kTRUE;
791
792 // Return return code
793 return rc;
794}
795
796// --------------------------------------------------------------------------
797//
798// do post processing (before eventloop) of all tasks in the task-list
799// only tasks which have successfully been preprocessed are postprocessed.
800//
801Int_t MTaskList::PostProcess()
802{
803 *fLog << all << "Postprocessing... " << flush;
804 if (fDisplay)
805 {
806 // Set status lines
807 fDisplay->SetStatusLine1("PostProcessing...");
808 fDisplay->SetStatusLine2("");
809 }
810
811 //
812 // Make sure, that the ReadyToSave flag is not reset from a tasklist
813 // running as a task in another tasklist.
814 //
815 const Bool_t noreset = fParList->TestBit(MParList::kDoNotReset);
816 if (!noreset)
817 {
818 fParList->SetBit(MParList::kDoNotReset);
819 fParList->Reset();
820 }
821
822 //
823 // create the Iterator for the TaskList
824 //
825 TIter Next(fTasks);
826
827 MTask *task=NULL;
828
829 //
830 // loop over all tasks for postprocessing
831 // only tasks which have successfully been preprocessed are postprocessed.
832 //
833 while ( (task=(MTask*)Next()) )
834 {
835 if (!task->CallPostProcess())
836 return kFALSE;
837
838 // Handle GUI events (display changes, mouse clicks)
839 if (fDisplay)
840 gSystem->ProcessEvents();
841 }
842
843 *fLog << all << endl;
844
845 //
846 // Reset the ReadyToSave flag.
847 //
848 if (!noreset)
849 {
850 fParList->SetReadyToSave(kFALSE);
851 fParList->ResetBit(MParList::kDoNotReset);
852 }
853
854 return kTRUE;
855}
856
857// --------------------------------------------------------------------------
858//
859// Prints the number of times all the tasks in the list has been.
860// For convinience the lvl argument results in a number of spaces at the
861// beginning of the line. So that the structur of a tasklist can be
862// identified. If a Tasklist or task has filter applied the name of the
863// filter is printer in <>-brackets behind the number of executions.
864// Use MTaskList::PrintStatistics without an argument.
865//
866void MTaskList::PrintStatistics(const Int_t lvl, Bool_t title, Double_t time) const
867{
868 if (lvl==0)
869 {
870 *fLog << all << underline << "Process execution Statistics:" << endl;
871 *fLog << GetDescriptor();
872 if (GetFilter())
873 *fLog << " <" << GetFilter()->GetName() << ">";
874 if (title)
875 *fLog << "\t" << fTitle;
876 if (time>=0)
877 *fLog << Form(" %5.1f", GetCpuTime()/time*100) << "%";
878 else
879 *fLog << " 100.0%";
880 *fLog << endl;
881 }
882 else
883 MTask::PrintStatistics(lvl, title, time);
884
885 //
886 // create the Iterator for the TaskList
887 //
888 fTasks->R__FOR_EACH(MTask, PrintStatistics)(lvl+1, title, GetCpuTime());
889
890 if (lvl==0)
891 *fLog << endl;
892}
893
894// --------------------------------------------------------------------------
895//
896// Call 'Print()' of all tasks
897//
898void MTaskList::Print(Option_t *) const
899{
900 *fLog << all << underline << GetDescriptor() << ":" << endl;
901
902 fTasks->Print();
903
904 *fLog << endl;
905}
906
907// --------------------------------------------------------------------------
908//
909// Implementation of SavePrimitive. Used to write the call to a constructor
910// to a macro. In the original root implementation it is used to write
911// gui elements to a macro-file.
912//
913void MTaskList::StreamPrimitive(ostream &out) const
914{
915 out << " MTaskList " << GetUniqueName();
916 if (fName!=gsDefName || fTitle!=gsDefTitle)
917 {
918 out << "(\"" << fName << "\"";
919 if (fTitle!=gsDefTitle)
920 out << ", \"" << fTitle << "\"";
921 out <<")";
922 }
923 out << ";" << endl << endl;
924
925 MIter Next(fTasks);
926
927 MParContainer *cont = NULL;
928 while ((cont=Next()))
929 {
930 cont->SavePrimitive(out, "");
931 out << " " << GetUniqueName() << ".AddToList(&";
932 out << cont->GetUniqueName() << ");" << endl << endl;
933 }
934}
935
936void MTaskList::GetNames(TObjArray &arr) const
937{
938 MParContainer::GetNames(arr);
939 fTasks->R__FOR_EACH(MParContainer, GetNames)(arr);
940}
941
942void MTaskList::SetNames(TObjArray &arr)
943{
944 MParContainer::SetNames(arr);
945 fTasks->R__FOR_EACH(MParContainer, SetNames)(arr);
946}
947
948// --------------------------------------------------------------------------
949//
950// Read the contents/setup of a parameter container/task from a TEnv
951// instance (steering card/setup file).
952// The key to search for in the file should be of the syntax:
953// prefix.vname
954// While vname is a name which is specific for a single setup date
955// (variable) of this container and prefix is something like:
956// evtloopname.name
957// While name is the name of the containers/tasks in the parlist/tasklist
958//
959// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
960// Job4.MImgCleanStd.CleaningLevel2: 2.5
961//
962// If this cannot be found the next step is to search for
963// MImgCleanStd.CleaningLevel1: 3.0
964// And if this doesn't exist, too, we should search for:
965// CleaningLevel1: 3.0
966//
967// Warning: The programmer is responsible for the names to be unique in
968// all Mars classes.
969//
970Int_t MTaskList::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
971{
972 if (print)
973 *fLog << all << "MTaskList::ReadEnv: " << prefix << " (" << (int)print << ")" << endl;
974
975 MParContainer *cont = NULL;
976
977 MIter Next(fTasks);
978 while ((cont=Next()))
979 {
980 if (cont->InheritsFrom("MTaskList"))
981 {
982 if (cont->ReadEnv(env, prefix, print)==kERROR)
983 return kERROR;
984 continue;
985 }
986
987 if (cont->TestEnv(env, prefix, print)==kERROR)
988 return kERROR;
989 }
990
991 return kTRUE;
992}
993
994// --------------------------------------------------------------------------
995//
996// Write the contents/setup of a parameter container/task to a TEnv
997// instance (steering card/setup file).
998// The key to search for in the file should be of the syntax:
999// prefix.vname
1000// While vname is a name which is specific for a single setup date
1001// (variable) of this container and prefix is something like:
1002// evtloopname.name
1003// While name is the name of the containers/tasks in the parlist/tasklist
1004//
1005// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
1006// Job4.MImgCleanStd.CleaningLevel2: 2.5
1007//
1008// If this cannot be found the next step is to search for
1009// MImgCleanStd.CleaningLevel1: 3.0
1010// And if this doesn't exist, too, we should search for:
1011// CleaningLevel1: 3.0
1012//
1013// Warning: The programmer is responsible for the names to be unique in
1014// all Mars classes.
1015//
1016Bool_t MTaskList::WriteEnv(TEnv &env, TString prefix, Bool_t print) const
1017{
1018 MParContainer *cont = NULL;
1019
1020 MIter Next(fTasks);
1021 while ((cont=Next()))
1022 if (!cont->WriteEnv(env, prefix, print))
1023 return kFALSE;
1024 return kTRUE;
1025}
1026
1027// --------------------------------------------------------------------------
1028//
1029// Removes a task from the tasklist. Returns kFALSE if the object was not
1030// found in the list.
1031//
1032Bool_t MTaskList::RemoveFromList(MTask *task)
1033{
1034 TObject *obj = fTasks->Remove(task);
1035
1036 //
1037 // If the task was found in the list try to remove it from the second
1038 // list, too.
1039 //
1040 if (obj)
1041 fTasksProcess.Remove(task);
1042
1043 return obj ? kTRUE : kFALSE;
1044
1045}
1046
1047// --------------------------------------------------------------------------
1048//
1049// Removes all task of the TList from the tasklist. Returns kFALSE if any
1050// of the objects was not an MTask or not found in the list.
1051//
1052Bool_t MTaskList::RemoveFromList(const TList &list)
1053{
1054 Bool_t rc = kTRUE;
1055
1056 TIter Next(&list);
1057 TObject *obj=0;
1058 while ((obj=Next()))
1059 {
1060 if (!obj->InheritsFrom(MTask::Class()))
1061 {
1062 *fLog << err << "ERROR - Object " << obj->GetName() << " doesn't inherit from MTask..." << endl;
1063 rc = kFALSE;
1064 continue;
1065 }
1066
1067 if (!RemoveFromList(static_cast<MTask*>(obj)))
1068 rc = kFALSE;
1069 }
1070 return rc;
1071}
1072
1073// --------------------------------------------------------------------------
1074//
1075// Find an object with the same name in the list and replace it with
1076// the new one. If the kIsOwner flag is set and the object was not
1077// created automatically, the object is deleted.
1078//
1079Bool_t MTaskList::Replace(MTask *task)
1080{
1081 //
1082 // check if the object (you want to add) exists
1083 //
1084 if (!task)
1085 return kFALSE;
1086
1087 if (task==this)
1088 {
1089 *fLog << warn << "WARNING - You cannot add a tasklist to itself. This" << endl;
1090 *fLog << " would create infinite recursions...ignored." << endl;
1091 return kFALSE;
1092
1093 }
1094
1095 MTask *obj = (MTask*)FindObject(task->GetName());
1096 if (!obj)
1097 {
1098 *fLog << warn << "No object with the same name '";
1099 *fLog << task->GetName() << "' in list... adding." << endl;
1100 return AddToList(task);
1101 }
1102
1103 if (task==obj)
1104 return kTRUE;
1105
1106 *fLog << inf2 << "Replacing " << task->GetName() << " in " << GetName() << " for " << obj->GetStreamId() << "... " << flush;
1107 task->SetStreamId(obj->GetStreamId());
1108 task->SetBit(kMustCleanup);
1109 fTasks->AddAfter((TObject*)obj, task);
1110 *fLog << "done." << endl;
1111
1112 RemoveFromList(obj);
1113
1114 if (TestBit(kIsOwner))
1115 delete obj;
1116
1117 //*fLog << inf << "MTask '" << task->GetName() << "' found and replaced..." << endl;
1118
1119 return kTRUE;
1120}
1121
1122// --------------------------------------------------------------------------
1123//
1124// Can be used to create an iterator over all tasks, eg:
1125// MTaskList tlist;
1126// TIter Next(tlist); // Be aware: Use a object here rather than a pointer!
1127// TObject *o=0;
1128// while ((o=Next()))
1129// {
1130// [...]
1131// }
1132//
1133MTaskList::operator TIterator*() const
1134{
1135 return new TListIter(fTasks);
1136}
Note: See TracBrowser for help on using the repository browser.