#include "AutoLocker.hxx"
#include <iostream>
+#include <iomanip>
#include <sstream>
+#include <algorithm> // std::replace_if
//#define _DEVDEBUG_
#include "YacsTrace.hxx"
switch (val->getType()->kind())
{
case Double:
- xmldump << "<value><double>" << val->getDoubleValue() << "</double></value>" << endl;
+ xmldump << "<value><double>" << setprecision(16) << val->getDoubleValue() << "</double></value>" << endl;
break;
case Int:
xmldump << "<value><int>" << val->getIntValue() << "</int></value>" << endl;
int ForEachLoopPassedData::toAbsIdNot(int localId) const
{
if(localId<0)
- throw YACS::Exception("ForEachLoopPassedData::toAbsId : local pos must be >= 0 !");
+ throw YACS::Exception("ForEachLoopPassedData::toAbsIdNot : local pos must be >= 0 !");
int ret(0),curLocId(0);
for(std::vector<bool>::const_iterator it=_flagsIds.begin();it!=_flagsIds.end();it++,ret++)
{
curLocId++;
}
}
- throw YACS::Exception("ForEachLoopPassedData::toAbsId : not referenced Id !");
+ throw YACS::Exception("ForEachLoopPassedData::toAbsIdNot : not referenced Id !");
}
int ForEachLoopPassedData::getNumberOfElementsToDo() const
{
AnySplitOutputPort *temp=new AnySplitOutputPort(*(*iter2),this);
InterceptorInputPort *interc=new InterceptorInputPort(*other._intecptrsForOutGoingPorts[i],this);
- temp->addRepr(getOutPort((*iter2)->getName()),interc);
+ temp->addRepr(getOutPort(other.getOutPortName((*iter2)->getRepr())),interc);
interc->setRepr(temp);
_outGoingPorts.push_back(temp);
_intecptrsForOutGoingPorts.push_back(interc);
DEBTRACE("ForEachLoop::exUpdateState");
if(_state == YACS::DISABLED)
return;
+ if(_state == YACS::DONE)
+ return;
if(_inGate.exIsReady())
{
//internal graph update
_execNodes[id]->exUpdateState();
_nbOfEltConsumed++;
_initializingCounter--;
+ _currentIndex++;
if (_initializingCounter == 0)
_initNode->setState(DONE);
return YACS::NOEVENT;
else
{
TypeCodeSeq *newTc=(TypeCodeSeq *)TypeCode::sequenceTc("","",port.first->edGetType());
- AnySplitOutputPort *newPort=new AnySplitOutputPort(getPortName(port.first),this,newTc);
- InterceptorInputPort *intercptor=new InterceptorInputPort(string("intercptr for ")+getPortName(port.first),this,port.first->edGetType());
+ // The out going ports belong to the ForEachLoop, whereas
+ // the delegated port belongs to a node child of the ForEachLoop.
+ // The name of the delegated port contains dots (bloc.node.outport),
+ // whereas the name of the out going port shouldn't do.
+ std::string outputPortName = getPortName(port.first);
+ std::replace_if (outputPortName.begin(), outputPortName.end(),
+ std::bind1st(std::equal_to<char>(), '.'), '_');
+ outputPortName += "_interceptor";
+ AnySplitOutputPort *newPort=new AnySplitOutputPort(outputPortName,this,newTc);
+ InterceptorInputPort *intercptor=new InterceptorInputPort(outputPortName + "_in",this,port.first->edGetType());
intercptor->setRepr(newPort);
newTc->decrRef();
newPort->addRepr(port.first,intercptor);
void ForEachLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
{
- if(isInMyDescendance(start->getNode())==_node)
- throw Exception("ForEachLoop::checkLinkPossibility : A link from work node to init node not permitted");
+ DynParaLoop::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
+ if(end->getNode() == &_splitterNode)
+ throw Exception("Illegal link within a foreach loop: \
+the 'SmplsCollection' port cannot be linked within the scope of the loop.");
+ if(end == &_nbOfBranches)
+ throw Exception("Illegal link within a foreach loop: \
+the 'nbBranches' port cannot be linked within the scope of the loop.");
}
std::list<OutputPort *> ForEachLoop::getLocalOutputPorts() const
std::string ForEachLoop::getProgress() const
{
- int nbElems = _splitterNode.getNumberOfElements();
+ int nbElems(getNbOfElementsToBeProcessed());
std::stringstream aProgress;
if (nbElems > 0)
aProgress << _currentIndex << "/" << nbElems;
return aProgress.str();
}
+//! Get the progress weight for all elementary nodes
+/*!
+ * Only elementary nodes have weight. For each node in the loop, the weight done is multiplied
+ * by the number of elements done and the weight total by the number total of elements
+ */
+list<ProgressWeight> ForEachLoop::getProgressWeight() const
+{
+ list<ProgressWeight> ret;
+ list<Node *> setOfNode=edGetDirectDescendants();
+ int elemDone=getCurrentIndex();
+ int elemTotal=getNbOfElementsToBeProcessed();
+ for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
+ {
+ list<ProgressWeight> myCurrentSet=(*iter)->getProgressWeight();
+ for(list<ProgressWeight>::iterator iter=myCurrentSet.begin();iter!=myCurrentSet.end();iter++)
+ {
+ (*iter).weightDone=((*iter).weightTotal) * elemDone;
+ (*iter).weightTotal*=elemTotal;
+ }
+ ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
+ }
+ return ret;
+}
+
+int ForEachLoop::getNbOfElementsToBeProcessed() const
+{
+ int nbBranches = _nbOfBranches.getIntValue();
+ return _splitterNode.getNumberOfElements()
+ + (_initNode ? nbBranches:0)
+ + (_finalizeNode ? nbBranches:0) ;
+}
+
/*!
* This method allows to retrieve the state of \a this during execution or after. This method works even if this is \b NOT complete, or during execution or after a failure in \a this.
* The typical usage of this method is to retrieve the results of items that passed successfully to avoid to lose all of them if only one fails.
void ForEachLoop::assignPassedResults(const std::vector<unsigned int>& passedIds, const std::vector<SequenceAny *>& passedOutputs, const std::vector<std::string>& nameOfOutputs)
{
delete _passedData;
+ _failedCounter=0;
_passedData=new ForEachLoopPassedData(passedIds,passedOutputs,nameOfOutputs);
}