-// Copyright (C) 2006-2014 CEA/DEN, EDF R&D
+// Copyright (C) 2006-2015 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
DynParaLoop::DynParaLoop(const std::string& name, TypeCode *typeOfDataSplitted)
: ComposedNode(name),_node(0),_initNode(0),_finalizeNode(0),_nbOfEltConsumed(0),
_nbOfBranches(NAME_OF_NUMBER_OF_BRANCHES,this,Runtime::_tc_int),
- _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted)
+ _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
{
}
DynParaLoop::DynParaLoop(const DynParaLoop& other, ComposedNode *father, bool editionOnly)
: ComposedNode(other,father), _nbOfBranches(other._nbOfBranches,this),
_splittedPort(other._splittedPort,this), _node(0), _initNode(0), _finalizeNode(0),
- _nbOfEltConsumed(0)
+ _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
{
if(other._node)
_node=other._node->clone(this,editionOnly);
_nbOfBranches.exInit(start);
_splittedPort.exInit();
_nbOfEltConsumed=0;
+ _failedCounter=0;
}
Node *DynParaLoop::edSetInitNode(Node *node)
return ComposedNode::getNumberOfOutputPorts()+1;
}
+/*!
+ * DynParaLoop creates at runtime (exupdateState) clone of nodes. One clone per branch.
+ * This method returns the id of the branch given the node \a node.
+ * If \a node is not a dynamically created node in \a this -1 is returned.
+ */
+int DynParaLoop::getBranchIDOfNode(Node *node) const
+{
+ if(_node)
+ {
+ for(std::vector<Node *>::const_iterator it=_execNodes.begin();it!=_execNodes.end();it++)
+ if(node==*it)
+ return std::distance(_execNodes.begin(),it);
+ }
+ if(_finalizeNode)
+ {
+ for(std::vector<Node *>::const_iterator it=_execFinalizeNodes.begin();it!=_execFinalizeNodes.end();it++)
+ if(node==*it)
+ return std::distance(_execFinalizeNodes.begin(),it);
+ }
+ if(_initNode)
+ {
+ for(std::vector<Node *>::const_iterator it=_execInitNodes.begin();it!=_execInitNodes.end();it++)
+ if(node==*it)
+ return std::distance(_execInitNodes.begin(),it);
+ }
+ return -1;
+}
+
std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
{
list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
{
string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
if(typeOfPortInstance!=InputPort::NAME)
- throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop this is not possible");
+ throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop is not possible");
}
void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
{
+ std::string linkName("(");
+ linkName += port.first->getName()+" to "+finalTarget->getName()+")";
if(_initNode)
if(isInMyDescendance(port.first->getNode())==_initNode)
- throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : a link starting from init node can't leave the scope of ForEachLoop node it belongs to.");
+ throw Exception(std::string("Illegal link within a parallel loop: \
+a link starting from the init node can't leave the scope of the loop.")
+ + linkName);
+
+ if(_finalizeNode)
+ if(isInMyDescendance(port.first->getNode())==_finalizeNode)
+ throw Exception(std::string("Illegal link within a parallel loop: \
+an output port of the finalize node can't be linked.")
+ + linkName);
+
if(port.first==&_splittedPort)
- throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : splitted port must be link within the scope of ForEachLoop node it belongs to.");
+ throw Exception(std::string("Illegal link within a parallel loop: \
+the 'evalSamples' port must be linked within the scope of the loop.")
+ + linkName);
}
void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
if(starts.size()!=1)
throw Exception(what);
//ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled.
- if(*(starts.begin())!=&_splittedPort)
- throw Exception(what);
if(alreadyFed==FREE_ST)
alreadyFed=FED_ST;
else if(alreadyFed==FED_ST)
std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
LinkInfo& info) const
{
- if(start==&_splittedPort)
fw[(ComposedNode *)this].push_back(start);
- else
- throw Exception("DynParaLoop::checkControlDependancy : Internal error occured - should never been called !");
+}
+
+void DynParaLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
+ InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
+{
+ ComposedNode::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
+ Node * startNode = isInMyDescendance(start->getNode());
+ Node * endNode = isInMyDescendance(end->getNode());
+ std::string linkName("(");
+ linkName += start->getName()+" to "+end->getName()+")";
+
+ if(start == &_splittedPort && endNode != _node)
+ throw Exception(std::string("Illegal link within a parallel loop: \
+the 'evalSamples' port can only be connected to the working node of the loop.")
+ + linkName);
+
+ if(_finalizeNode && _finalizeNode == startNode)
+ throw Exception(std::string("Illegal link within a parallel loop: \
+the finalize node can't be the origin of a link.")
+ + linkName);
+
+ if(_initNode && _node == startNode && _initNode == endNode)
+ throw Exception(std::string("Illegal link within a parallel loop: \
+can't make a link from the working node to the init node.")
+ + linkName);
+
+ if(_finalizeNode && _node == startNode && _finalizeNode == endNode)
+ throw Exception(std::string("Illegal link within a parallel loop: \
+can't make a link from the working node to the finalize node.")
+ + linkName);
}
/*!
* \param node : the child node that has failed
* \return the state change
*/
-YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node)
+YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
{
DEBTRACE("DynParaLoop::updateStateOnFailedEventFrom " << node->getName());
setState(YACS::FAILED);
treeToDup.appendTask(*iter, (*iter)->getDynClonerIfExists(this));
}
}
+
+ // Build the links between clones.
+ // Only the links starting from initNode are possible.
+ if(_initNode)
+ {
+ std::vector< std::pair<OutPort *, InPort *> > outLinks = _initNode->getSetOfLinksLeavingCurrentScope();
+ std::vector< std::pair<OutPort *, InPort *> >::const_iterator it;
+ for(it=outLinks.begin(); it!=outLinks.end(); it++)
+ {
+ OutPort *startPort = it->first;
+ InPort *endPort = it->second;
+ Node* destNode = isInMyDescendance(endPort->getNode());
+ if(destNode == _node)
+ edAddLink(clones[0]->getOutPort(startPort->getName()),
+ clones[1]->getInPort(endPort->getName()));
+ if(destNode == _finalizeNode)
+ edAddLink(clones[0]->getOutPort(startPort->getName()),
+ clones[2]->getInPort(endPort->getName()));
+ }
+ }
DEBTRACE("Placing nodes...")
vector<Container *> conts=treeToDup.getAllContainers();
return _finalizeNode;
}
+int DynParaLoop::getMaxLevelOfParallelism() const
+{
+ return _nbOfBranches.getIntValue() * _node->getMaxLevelOfParallelism();
+}
+
void DynParaLoop::shutdown(int level)
{
if(level==0)return;