void PeggingIterator::followPegging (const OperationPlan* op, double qty, double offset, short lvl) { // Zero quantity operationplans don't have further pegging if (!op->getQuantity()) return; // For each flowplan ask the buffer to find the pegged operationplans. if (downstream) for (OperationPlan::FlowPlanIterator i = op->beginFlowPlans(); i != op->endFlowPlans(); ++i) { if (i->getQuantity() > ROUNDING_ERROR) // Producing flowplan i->getFlow()->getBuffer()->followPegging(*this, &*i, qty, offset, lvl+1); } else for (OperationPlan::FlowPlanIterator i = op->beginFlowPlans(); i != op->endFlowPlans(); ++i) { if (i->getQuantity() < -ROUNDING_ERROR) // Consuming flowplan i->getFlow()->getBuffer()->followPegging(*this, &*i, qty, offset, lvl+1); } // Push child operationplans on the stack. // The pegged quantity is equal to the ratio of the quantities of the // parent and child operationplan. for (OperationPlan::iterator j(op); j != OperationPlan::end(); ++j) updateStack( &*j, qty * j->getQuantity() / op->getQuantity(), offset * j->getQuantity() / op->getQuantity(), lvl+1 ); }
DECLARE_EXPORT Flow::~Flow() { // Set a flag to make sure the level computation is triggered again HasLevel::triggerLazyRecomputation(); // Delete existing flowplans if (getOperation() && getBuffer()) { // Loop over operationplans for(OperationPlan::iterator i(getOperation()); i != OperationPlan::end(); ++i) // Loop over flowplans for(OperationPlan::FlowPlanIterator j = i->beginFlowPlans(); j != i->endFlowPlans(); ) if (j->getFlow() == this) j.deleteFlowPlan(); else ++j; } // Delete the flow from the operation and the buffer if (getOperation()) getOperation()->flowdata.erase(this); if (getBuffer()) getBuffer()->flows.erase(this); }
DECLARE_EXPORT Flow::~Flow() { // Set a flag to make sure the level computation is triggered again HasLevel::triggerLazyRecomputation(); // Delete existing flowplans if (getOperation() && getBuffer()) { // Loop over operationplans for(OperationPlan::iterator i(getOperation()); i != OperationPlan::end(); ++i) // Loop over flowplans for(OperationPlan::FlowPlanIterator j = i->beginFlowPlans(); j != i->endFlowPlans(); ) if (j->getFlow() == this) j.deleteFlowPlan(); else ++j; } // Delete the flow from the operation and the buffer if (getOperation()) getOperation()->flowdata.erase(this); if (getBuffer()) getBuffer()->flows.erase(this); // Clean up alternate flows if (hasAlts) { // The flow has alternates. // Make a new flow the leading one. Or if there is only one alternate // present it is not marked as an alternate any more. unsigned short cnt = 0; int minprio = INT_MAX; Flow* newLeader = NULL; for (Operation::flowlist::iterator i = getOperation()->flowdata.begin(); i != getOperation()->flowdata.end(); ++i) if (i->altFlow == this) { cnt++; if (i->priority < minprio) { newLeader = &*i; minprio = i->priority; } } if (cnt < 1) throw LogicException("Alternate flows update failure"); else if (cnt == 1) // No longer an alternate any more newLeader->altFlow = NULL; else { // Mark a new leader flow newLeader->hasAlts = true; newLeader->altFlow = NULL; for (Operation::flowlist::iterator i = getOperation()->flowdata.begin(); i != getOperation()->flowdata.end(); ++i) if (i->altFlow == this) i->altFlow = newLeader; } } if (altFlow) { // The flow is an alternate of another one. // If it was the only alternate, then the hasAlts flag on the parent // flow needs to be set back to false bool only_one = true; for (Operation::flowlist::iterator i = getOperation()->flowdata.begin(); i != getOperation()->flowdata.end(); ++i) if (i->altFlow == altFlow) { only_one = false; break; } if (only_one) altFlow->hasAlts = false; } }