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

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