void CRUTopologicalDGIterator::Build() { TaskLink link; // Fill the data structures by references to available tasks DSListPosition pos = GetAllTasksList().GetHeadPosition(); while (NULL != pos) { CRUTask *pTask = GetAllTasksList().GetNext(pos); link.pTask_ = pTask; // The tasks that need to be traversed before me CRUTaskList &refTaskList = (DIRECT == dir_) ? pTask->GetTasksThatIDependOn() : pTask->GetTasksThatDependOnMe(); link.refCount_ = refTaskList.GetCount(); // Place the link into the hash allTasksLinkMap_[pTask->GetId()] = link; // If this is a ready task, // place a reference to it into the ready list if (0 == link.refCount_) { readyTasksList_.AddHead(link.pTask_); } } // My guess is that this is a circular graph RUASSERT(FALSE == readyTasksList_.IsEmpty()); SetCurrentTask(readyTasksList_.RemoveHead()); }
void CRUTopologicalDGIterator::Next() { RUASSERT(FALSE == allTasksLinkMap_.IsEmpty()); CRUTask *pTask = GetCurrentTask(); if (NULL == pTask) { return; // all the tasks have been already traversed } // The tasks that need to be traversed after me CRUTaskList &refTaskList = (DIRECT == dir_) ? pTask->GetTasksThatDependOnMe() : pTask->GetTasksThatIDependOn(); // For all of these tasks, decrecase the reference count // Update the "ready" list, if any of the tasks have become ready. UpdateIterator(refTaskList); // Select a new current task if (TRUE == readyTasksList_.IsEmpty()) { SetCurrentTask(NULL); // The last task has just been traversed } else { // Retrieve a new task from the "ready" list SetCurrentTask(readyTasksList_.RemoveHead()); } }
void CRUTopologicalDGIterator::UpdateIterator(CRUTaskList &taskList) { TaskLink link = {NULL, 0}; DSListPosition pos = taskList.GetHeadPosition(); while (NULL != pos) { CRUTask *pTask = taskList.GetNext(pos); // Locate the link in the link map BOOL ret = allTasksLinkMap_.Lookup(pTask->GetId(), link); RUASSERT(TRUE == ret); // One reference less to the task link.refCount_--; if (0 == link.refCount_) { // One more task has no dependencies, place it to the ready list readyTasksList_.AddHead(link.pTask_); } else { // Update the link's reference count in the hash allTasksLinkMap_[pTask->GetId()] = link; } } }
void CRUDependenceGraph::DumpGraph(CDSString &to) { to += "\n\t\tDEPENDENCE GRAPH DRAWING START\n"; to += "digraph G { \n\n"; to += " graph [ fontname = \"Helvetica-Oblique\",page = \"8,10\", margin = \"1.5,1.5\"];\n\n"; to += "node [style=filled,fontsize=14];\n\n"; CRUTask *pTask; CRUTopologicalDGIterator firstPass(*this, CRUTopologicalDGIterator::DIRECT); for (; (pTask = firstPass.GetCurrentTask()) != NULL; firstPass.Next()) { pTask->DumpGraphNode(to); } CRUTopologicalDGIterator secondPass(*this, CRUTopologicalDGIterator::DIRECT); for (; (pTask = secondPass.GetCurrentTask()) != NULL; secondPass.Next()) { pTask->DumpGraphEdges(to); } to += "\n}\n\n\t\tDEPENDENCE GRAPH DRAWING END\n"; }
//--------------------------------------------------------------------------// // CRUTask::Dump() // // Called by CRUDependenceGraph::Dump() // // Prints the "standard" task's dump //--------------------------------------------------------------------------// // LCOV_EXCL_START :dpm void CRUTask::Dump(CDSString &to) { char idStr[10]; sprintf(idStr,"%d",GetId()); to += "\nTASK ID = " + CDSString(idStr); to += "\n\t" + GetTaskName() + "\n"; if (0 == pSuccList_->GetCount()) { to += "\tNo tasks depend on me.\n"; } else { to += "\tTasks that depend on me:\n"; DSListPosition pos = pSuccList_->GetHeadPosition(); while (NULL != pos) { CRUTask *pTask = pSuccList_->GetNext(pos); sprintf(idStr,"%d",pTask->GetId()); to += "\t\tTask id = " + CDSString(idStr) + "\n"; } } }
void CRUDependenceGraph::ComputeGainFunction() { CRUTask *pTask; CRUTopologicalDGIterator it(*this, CRUTopologicalDGIterator::REVERSE); for (; (pTask = it.GetCurrentTask()) != NULL; it.Next()) { pTask->ComputeGain(); } }
void CRUDependenceGraph::Dump(CDSString &to) { to += "\n\t\tDEPENDENCE GRAPH DUMP\n"; CRUTask *pTask; CRUTopologicalDGIterator it(*this, CRUTopologicalDGIterator::DIRECT); for (; (pTask = it.GetCurrentTask()) != NULL; it.Next()) { pTask->Dump(to); } }
void CRUTask::RemoveAllTasksThatIDependOn() { DSListPosition pos = GetTasksThatIDependOn().GetHeadPosition(); while (NULL != pos) { CRUTask *pFromTask = GetTasksThatIDependOn().GetNext(pos); pFromTask->GetTasksThatDependOnMe().RemoveRefToTask(this); } GetTasksThatIDependOn().RemoveAll(); }
void CRUDependenceGraph::ScheduleDoomedTask() { CRUTask *pTask; CRUTopologicalDGIterator it(*this, CRUTopologicalDGIterator::DIRECT); for (; (pTask = it.GetCurrentTask()) != NULL; it.Next()) { if (0 != pTask->GetStatus()) { pScheduledTask_ = pTask; return; } } }
BOOL CRUDependenceGraph::AllEmpCheckTasksComplete() const { DSListPosition pos = availableTaskList_.GetHeadPosition(); while (NULL != pos) { CRUTask *pTask = availableTaskList_.GetNext(pos); if( CRUTask::EMP_CHECK == pTask->GetType() ) { return FALSE; } } return TRUE; }
CRUTask *CRUTaskList::FindTask(Lng32 taskId) { DSListPosition pos = GetHeadPosition(); while (NULL != pos) { CRUTask *pTask = GetNext(pos); if (pTask->GetId() == taskId) { return pTask; } } return NULL; }
void CRUTask::HandlePredecessorFailure(CRUTask &task) { RUASSERT (0 != task.GetStatus()); // If there is already something wrong, don't touch me if (0 != this->GetStatus()) { return; } // The error's text will be printed only for the Refresh tasks. CRUException &ex = GetErrorDesc(); ex.SetError(IDS_RU_TASK_PREDECESSOR_PROBLEM); ex.AddArgument(this->GetTaskName()); ex.AddArgument(task.GetTaskName()); }
CRUTask *CRUDependenceGraph::GetTask(TInt64 objUid, CRUTask::Type type) { DSListPosition pos = availableTaskList_.GetHeadPosition(); while (NULL != pos) { CRUTask *pTask = availableTaskList_.GetNext(pos); if (TRUE == pTask->HasObject(objUid) && type == pTask->GetType() ) { return pTask; } } return NULL; }
//--------------------------------------------------------------------------// // CRUTask::DumpGraphNode() // // Called by CRUDependenceGraph::DumpGraph() // // Prints the task's edges dump acceptable for the Dotty GUI // //--------------------------------------------------------------------------// // LCOV_EXCL_START :dpm void CRUTask::DumpGraphEdges(CDSString &to) { if (0 == pSuccList_->GetCount()) { return; } char fromChr[10],toChr[10]; sprintf(fromChr,"%d",GetId()); CDSString fromStr(fromChr); fromStr = "\t\t" + fromStr + " -> "; DSListPosition pos = pSuccList_->GetHeadPosition(); while (NULL != pos) { CRUTask *pTask = pSuccList_->GetNext(pos); sprintf(toChr,"%d",pTask->GetId()); to += fromStr + CDSString(toChr) + ";\n"; } }
void CRUTask::ComputeGain() { TInt32 gain=0, maxGain=0; // First, update the (local) cost estimate ComputeCost(); // Next, update the (global) gain estimate DSListPosition pos = pSuccList_->GetHeadPosition(); // Compute the maximum gain between successor tasks while (NULL != pos) { CRUTask *pSuccTask = pSuccList_->GetNext(pos); gain = pSuccTask->GetGain(); maxGain = (gain > maxGain) ? gain : maxGain; } // Update the gain gain_ = GetCost() + maxGain; }
void CRUDependenceGraph::ScheduleNormalTask() { ComputeGainFunction(); CRUTopologicalDGIterator it(*this, CRUTopologicalDGIterator::DIRECT); CRUTask *pTask; for (; (pTask = it.GetCurrentTask()) != NULL; it.Next()) { RUASSERT (0 == pTask->GetStatus()); // Consider only ready tasks that are not being executed already if (FALSE == pTask->IsReady() || TRUE == pTask->IsRunning()) { continue; } // Examine the task's candidateship ... ConsiderTaskForScheduling(pTask); } }