/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz 12/2000 (tbretz@uni-sw.gwdg.de) ! ! Copyright: MAGIC Software Development, 2000-2001 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // // MTaskList // // // // Collection of tasks. // // // // A tasklist is necessary to run the eventloop. It contains the scheduled // // tasks, which should be executed in your program. // // // // To add a task use AddToList. // // // // The tasklist itself is a task, too. You can add a tasklist to another // // tasklist. This makes sense, if you want to filter the execution of // // more than one task of your tasklist using the same filter. // // // // The tasks in the list are idetified by their names. If more than one // // task has the same name, the tasklist will still work correctly, but // // you might run into trouble trying to get a pointer to a task by name // // from the list. // // // ///////////////////////////////////////////////////////////////////////////// #include "MTaskList.h" #include "MLog.h" #include "MLogManip.h" #include "MFilter.h" #include "MParList.h" #include "MInputStreamID.h" ClassImp(MTaskList); // -------------------------------------------------------------------------- // // the name for the task list must be the same for all task lists // because the task list (at the moment) is identified by exactly // this name in the parameter list (by MEvtLoop::SetParList) // MTaskList::MTaskList(const char *name, const char *title) { *fName = name ? name : "MTaskList"; *fTitle = title ? title : "A list for tasks to be executed"; } // -------------------------------------------------------------------------- // // CopyConstructor // creates a new TaskList and put the contents of an existing // TaskList in the new TaskList. // MTaskList::MTaskList(MTaskList &ts) { fTasks.AddAll(&ts.fTasks); } // -------------------------------------------------------------------------- // // If the 'IsOwner' bit is set (via SetOwner()) all tasks are deleted // by the destructor // MTaskList::~MTaskList() { if (TestBit(kIsOwner)) fTasks.SetOwner(); } // -------------------------------------------------------------------------- // // If the 'IsOwner' bit is set (via SetOwner()) all containers are deleted // by the destructor // inline void MTaskList::SetOwner(Bool_t enable=kTRUE) { enable ? SetBit(kIsOwner) : ResetBit(kIsOwner); } // -------------------------------------------------------------------------- // // Set the logging stream for the all tasks in the list and the tasklist // itself. // void MTaskList::SetLogStream(MLog *log) { // // create the Iterator over the tasklist // TIter Next(&fTasks); MTask *task=NULL; // // loop over all tasks for preproccesing // while ((task=(MTask*)Next())) task->SetLogStream(log); MParContainer::SetLogStream(log); } // -------------------------------------------------------------------------- // // schedule task for execution, whether as first task, or after // 'where'. 'tType' is the event type which should be processed // Bool_t MTaskList::AddToList(MTask *task, const char *type, MTask *where) { // FIXME: We agreed to put the task into list in an ordered way. // // Sanity check // if (!task) return kFALSE; // // Get Name of new task // const char *name = task->GetName(); // // Check if the new task is already existing in the list // const TObject *objn = fTasks.FindObject(name); const TObject *objt = fTasks.FindObject(task); if (objn || objt) { // // If the task is already in the list ignore it. // if (objt || objn==task) { *fLog << dbginf << "Warning: Task '" << task->GetName() << ", 0x" << (void*)task; *fLog << "' already existing in '" << GetName() << "'... ignoring." << endl; return kTRUE; } // // Otherwise add it to the list, but print a warning message // *fLog << dbginf << "Warning: Task with the same name '" << task->GetName(); *fLog << "' already existing in '" << GetName() << "'." << endl; *fLog << "You may not be able to get a pointer to this task by name." << endl; } if (where) { if (!fTasks.FindObject(where)) { *fLog << dbginf << "Error: Cannot find task after which the new task should be scheduled!" << endl; return kFALSE; } } *fLog << "Adding " << name << " to " << GetName() << " for " << type << "... " << flush; task->SetStreamId(type); fTasks.Add(task); *fLog << "Done." << endl; return kTRUE; } // -------------------------------------------------------------------------- // // Find an object in the list. // 'name' is the name of the object you are searching for. // TObject *MTaskList::FindObject(const char *name) const { return fTasks.FindObject(name); } // -------------------------------------------------------------------------- // // check if the object is in the list or not // TObject *MTaskList::FindObject(TObject *obj) const { return fTasks.FindObject(obj); } // -------------------------------------------------------------------------- // // do pre processing (before eventloop) of all tasks in the task-list // Bool_t MTaskList::PreProcess(MParList *pList) { *fLog << "Preprocessing... " << flush; fParList = pList; // // create the Iterator over the tasklist // TIter Next(&fTasks); MTask *task=NULL; // // loop over all tasks for preproccesing // while ((task=(MTask*)Next())) { *fLog << task->GetName() << "... " << flush; if (!task->PreProcess(fParList)) return kFALSE; task->SetIsPreprocessed(); } *fLog << endl; return kTRUE; } // -------------------------------------------------------------------------- // // do the event execution of all tasks in the task-list // Bool_t MTaskList::Process() { // // Reset the ReadyToSave flag. // Reset all containers. // // FIXME: To run a tasklist as a single task in another tasklist we // have to make sure, that the Parameter list isn't reset. // fParList->SetReadyToSave(kFALSE); fParList->Reset(); // // create the Iterator for the TaskList // TIter Next(&fTasks); MTask *task=NULL; // // loop over all tasks for processing // while ( (task=(MTask*)Next()) ) { // // if the task has the wrong stream id skip it. // if (strcmp(GetStreamId(), task->GetStreamId()) && strcmp(task->GetStreamId(), "All")) continue; // // Check for the existance of a filter. If a filter is existing // check for its value. If the value is kFALSE don't execute // this task. // const MFilter *filter = task->GetFilter(); const Bool_t rc = filter ? filter->IsExpressionTrue() : kTRUE; if (!rc) continue; // // if it has the right stream id execute the Process() function // and check what the result of it is. // switch (task->Process()) { case kTRUE: // // everything was OK: go on with the next task // continue; case kFALSE: // // an error occured: stop eventloop // return kFALSE; case kCONTINUE: // // something occured: skip the rest of the tasks for this event // return kTRUE; } } return kTRUE; } // -------------------------------------------------------------------------- // // do post processing (before eventloop) of all tasks in the task-list // only tasks which have successfully been preprocessed are postprocessed. // Bool_t MTaskList::PostProcess() { *fLog << "Postprocessing... " << flush; // // Reset the ReadyToSave flag. // Reset all containers. // // FIXME: To run a tasklist as a single task in another tasklist we // have to make sure, that the Parameter list isn't reset. // fParList->SetReadyToSave(kFALSE); fParList->Reset(); // // create the Iterator for the TaskList // TIter Next(&fTasks); MTask *task=NULL; // // loop over all tasks for postprocessing // only tasks which have successfully been preprocessed are postprocessed. // while ( (task=(MTask*)Next()) ) { if (!task->IsPreprocessed()) continue; *fLog << task->GetName() << "... " << flush; // // FIXME: should we only skip this task? // if (!task->PostProcess()) return kFALSE; } *fLog << endl; return kTRUE; } // -------------------------------------------------------------------------- void MTaskList::Print(Option_t *t) { *fLog << "TaskList: " << this->GetName() << " <" << this->GetTitle() << ">" << endl; fTasks.Print(); *fLog << endl; }