1 // Copyright (C) 2006-2020 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "DynParaLoop.hxx"
21 #include "LinkInfo.hxx"
22 #include "OutPort.hxx"
23 #include "Container.hxx"
24 #include "ComponentInstance.hxx"
25 #include "ServiceNode.hxx"
26 #include "InlineNode.hxx"
27 #include "ElementaryNode.hxx"
28 #include "Visitor.hxx"
34 #include "YacsTrace.hxx"
37 using namespace YACS::ENGINE;
39 const char DynParaLoop::NAME_OF_SPLITTED_SEQ_OUT[] = "evalSamples";
40 const char DynParaLoop::OLD_NAME_OF_SPLITTED_SEQ_OUT[] = "SmplPrt"; // For backward compatibility with 5.1.4
42 DynParaLoop::DynParaLoop(const std::string& name, TypeCode *typeOfDataSplitted, std::unique_ptr<NbBranchesAbstract>&& branchManager)
43 : ComposedNode(name),_node(0),_initNode(0),_finalizeNode(0),_nbOfEltConsumed(0),
44 _nbOfBranches(std::move(branchManager)),
45 _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(), _loopWeight(0)
47 _weight.setDefaultLoop();
50 DynParaLoop::~DynParaLoop()
57 DynParaLoop::DynParaLoop(const DynParaLoop& other, ComposedNode *father, bool editionOnly)
58 : ComposedNode(other,father),_nbOfBranches(other._nbOfBranches->copy(this)),
59 _splittedPort(other._splittedPort,this), _node(0), _initNode(0), _finalizeNode(0),
60 _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0),_weight(other._weight), _loopWeight(other._loopWeight)
63 _node=other._node->clone(this,editionOnly);
65 _initNode=other._initNode->clone(this,editionOnly);
66 if(other._finalizeNode)
67 _finalizeNode = other._finalizeNode->clone(this,editionOnly);
68 const AnyOutputPort& startOfLinksToReproduce=other._splittedPort;
69 set<InPort *> endsOfLinksToReproduce=startOfLinksToReproduce.edSetInPort();
70 for(set<InPort *>::iterator iter=endsOfLinksToReproduce.begin();iter!=endsOfLinksToReproduce.end();iter++)
71 edAddLink(&_splittedPort,getInPort(other.getPortName(*iter)));
74 Node *DynParaLoop::edSetNode(Node *node)
76 return checkConsistencyAndSetNode(_node, node);
79 //! This method is used to factorize methods edSetNode, edSetInitNode and edSetFinalizeNode
80 Node * DynParaLoop::checkConsistencyAndSetNode(Node* &nodeToReplace, Node* node)
82 if (node == NULL || nodeToReplace == node)
85 throw Exception(string("Can't set node: node ") + node->getName() + " is not orphan.");
86 if (_node && _node != nodeToReplace && _node->getName() == node->getName())
87 throw Exception(string("Can't set node: node ") + node->getName() +
88 " has the same name than exec node already in " + _name + ".");
89 if (_initNode && _initNode != nodeToReplace && _initNode->getName() == node->getName())
90 throw Exception(string("Can't set node: node ") + node->getName() +
91 " has the same name than init node already in " + _name + ".");
92 if (_finalizeNode && _finalizeNode != nodeToReplace && _finalizeNode->getName() == node->getName())
93 throw Exception(string("Can't set node: node ") + node->getName() +
94 " has the same name than finalize node already in " + _name + ".");
95 checkNoCrossHierachyWith(node);
96 ComposedNode::edRemoveChild(nodeToReplace);
97 Node * ret = nodeToReplace;
99 nodeToReplace->_father = this;
100 // set _modified flag so that edUpdateState can refresh state
105 void DynParaLoop::init(bool start)
107 ComposedNode::init(start);
110 string what("DynParaLoop::init : no node specified for ForEachLoop with name "); what +=_name;
111 throw Exception(what);
114 if (_initNode) _initNode->init(start);
115 if (_finalizeNode) _finalizeNode->init(start);
116 _nbOfBranches->exInit(start);
117 _splittedPort.exInit();
122 Node *DynParaLoop::edSetInitNode(Node *node)
124 return checkConsistencyAndSetNode(_initNode, node);
127 Node * DynParaLoop::edSetFinalizeNode(Node * node)
129 return checkConsistencyAndSetNode(_finalizeNode, node);
132 //! Connect an OutPort to an InPort and add control link if necessary
134 * Connect the ports with a data link (edAddLink)
135 * In a Loop don't add control flow link : use this only to add data back links
137 * \param start : the OutPort to connect
138 * \param end : the InPort to connect
139 * \return true if a new link has been created, false otherwise.
141 bool DynParaLoop::edAddDFLink(OutPort *start, InPort *end)
143 return edAddLink(start,end);
146 int DynParaLoop::getNumberOfInputPorts() const
148 return ComposedNode::getNumberOfInputPorts()+1;
151 int DynParaLoop::getNumberOfOutputPorts() const
153 return ComposedNode::getNumberOfOutputPorts()+1;
157 * DynParaLoop creates at runtime (exupdateState) clone of nodes. One clone per branch.
158 * This method returns the id of the branch given the node \a node.
159 * If \a node is not a dynamically created node in \a this -1 is returned.
161 int DynParaLoop::getBranchIDOfNode(Node *node) const
165 for(std::vector<Node *>::const_iterator it=_execNodes.begin();it!=_execNodes.end();it++)
167 return std::distance(_execNodes.begin(),it);
171 for(std::vector<Node *>::const_iterator it=_execFinalizeNodes.begin();it!=_execFinalizeNodes.end();it++)
173 return std::distance(_execFinalizeNodes.begin(),it);
177 for(std::vector<Node *>::const_iterator it=_execInitNodes.begin();it!=_execInitNodes.end();it++)
179 return std::distance(_execInitNodes.begin(),it);
184 std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
186 list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
187 ret.push_back((OutputPort *)&_splittedPort);
191 std::list<OutputPort *> DynParaLoop::getLocalOutputPorts() const
193 list<OutputPort *> ret=ComposedNode::getLocalOutputPorts();
194 ret.push_back((OutputPort *)&_splittedPort);
198 OutPort *DynParaLoop::getOutPort(const std::string& name) const
200 if (name == NAME_OF_SPLITTED_SEQ_OUT || name == OLD_NAME_OF_SPLITTED_SEQ_OUT)
201 return (OutPort *)&_splittedPort;
202 return ComposedNode::getOutPort(name);
206 OutputPort *DynParaLoop::getOutputPort(const std::string& name) const
208 if (name == NAME_OF_SPLITTED_SEQ_OUT || name == OLD_NAME_OF_SPLITTED_SEQ_OUT)
209 return (OutputPort *)&_splittedPort;
210 return ComposedNode::getOutputPort(name);
213 bool DynParaLoop::isPlacementPredictableB4Run() const
218 Node *DynParaLoop::edRemoveNode()
220 return removeNode(_node);
223 //! This method is used to factorize methods edRemoveNode, edRemoveInitNode and edRemoveFinalizeNode
224 Node * DynParaLoop::removeNode(Node* &nodeToRemove)
228 ComposedNode::edRemoveChild(nodeToRemove);
229 Node * ret = nodeToRemove;
235 Node *DynParaLoop::edRemoveInitNode()
237 return removeNode(_initNode);
240 Node * DynParaLoop::edRemoveFinalizeNode()
242 return removeNode(_finalizeNode);
245 void DynParaLoop::edRemoveChild(Node *node)
247 ComposedNode::edRemoveChild(node);
252 if(node==_finalizeNode)
257 bool DynParaLoop::edAddChild(Node *DISOWNnode)
259 return edSetNode(DISOWNnode);
262 std::list<Node *> DynParaLoop::edGetDirectDescendants() const
266 ret.push_back(_node);
268 ret.push_back(_initNode);
270 ret.push_back(_finalizeNode);
274 std::list<InputPort *> DynParaLoop::getSetOfInputPort() const
276 list<InputPort *> ret=ComposedNode::getSetOfInputPort();
277 InputPort *port(_nbOfBranches->getPort());
283 InputPort *DynParaLoop::getInputPort(const std::string& name) const
285 if(_nbOfBranches->isMyName(name))
286 return _nbOfBranches->getPort();
287 return ComposedNode::getInputPort(name);
290 std::list<InputPort *> DynParaLoop::getLocalInputPorts() const
292 list<InputPort *> ret=ComposedNode::getLocalInputPorts();
293 InputPort *port(_nbOfBranches->getPort());
299 unsigned DynParaLoop::getNumberOfBranchesCreatedDyn() const
301 if(_execNodes.empty())
302 throw Exception("ForEachLoop::getNumberOfBranches : No branches created dynamically ! - ForEachLoop needs to run or to be runned to call getNumberOfBranches");
304 return _execNodes.size();
307 Node *DynParaLoop::getChildByShortName(const std::string& name) const
309 if (_node && name == _node->getName())
311 if (_initNode && name == _initNode->getName())
313 if (_finalizeNode && name == _finalizeNode->getName())
314 return _finalizeNode;
315 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
316 throw Exception(what);
319 Node *DynParaLoop::getChildByNameExec(const std::string& name, unsigned id) const
321 if(id>=getNumberOfBranchesCreatedDyn())
322 throw Exception("ForEachLoop::getChildByNameExec : invalid id - too large compared with dynamically created branches.");
323 if (_node && name == _node->getName())
324 return _execNodes[id];
325 if (_initNode && name == _initNode->getName())
326 return _execInitNodes[id];
327 if (_finalizeNode && name == _finalizeNode->getName())
328 return _execFinalizeNodes[id];
329 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
330 throw Exception(what);
333 void DynParaLoop::cleanDynGraph()
335 vector<Node *>::iterator iter;
336 for(iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
339 for(iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
341 _execInitNodes.clear();
342 for(iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
344 _execFinalizeNodes.clear();
348 * This method applies on newly cloned on exec nodes (_execNodes/_execInitNodes)
349 * the setting of input ports coming from outside of 'this'
351 void DynParaLoop::prepareInputsFromOutOfScope(int branchNb)
353 set< InPort * > portsToSetVals=getAllInPortsComingFromOutsideOfCurrentScope();
355 // This tweak is to fix problems with nested dynamic loops where links are not cloned properly
356 list<InPort *> temp = getSetOfInPort();
357 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
359 if ((*iter2)->edSetOutPort().size() == 1 && *(*iter2)->edSetOutPort().begin() == NULL)
361 portsToSetVals.insert(*iter2);
365 // local input ports are not candidates for dynamically duplicated inport.
366 list<InputPort *> localPorts = getLocalInputPorts();
367 for(list<InputPort *>::iterator iter = localPorts.begin() ; iter != localPorts.end() ; iter++)
368 portsToSetVals.erase(*iter);
369 for(set< InPort * >::iterator iter=portsToSetVals.begin();iter!=portsToSetVals.end();iter++)
371 InputPort *curPortCasted=(InputPort *) *iter;//Cast granted by ForEachLoop::buildDelegateOf(InPort)
372 void *val=curPortCasted->get();
373 InputPort *portToSet=getDynInputPortByAbsName(branchNb,getInPortName(*iter),true);
374 if(portToSet)//portToSet==0 in case of portToSet==_splitterNode._dataPortToDispatch of ForEach
376 portToSet->put((const void *)val);
377 portToSet->edNotifyReferencedBy(nullptr,false);//This is to indicate that somewhere somebody deals with this inputport
378 //even if no direct physical link exists. This exclusively for _execNodes[branchNb]::init on the next turn of loop.
379 //false is put as 2nd parameter to tell to portToSet, do not touch to the data in case of squeezeMemory.
384 void DynParaLoop::putValueOnBranch(Any *val, unsigned branchId, bool first)
386 bool isDispatched = false;
387 set<InPort *> inPrtLkdWthSplttdPrt=_splittedPort.edSetInPort();
388 for(set<InPort *>::iterator iter=inPrtLkdWthSplttdPrt.begin();iter!=inPrtLkdWthSplttdPrt.end();iter++)
390 std::string portNameOnCurPrt=getPortName(*iter);
391 InputPort *portOnGivenBranch=getDynInputPortByAbsName(branchId,portNameOnCurPrt,first);//Cast granted because impossible to have cross protocol with _splittedPort
392 //see OptimizerLoop::buildDelegateOf
393 if(portOnGivenBranch)
396 portOnGivenBranch->edNotifyReferencedBy(0);
397 InputPort *traducer=getRuntime()->adapt(portOnGivenBranch,
398 Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME,_splittedPort.edGetType());
399 traducer->put((const void *)val);
401 if(traducer!=portOnGivenBranch)
407 Any *tmp=val->clone();
408 _splittedPort.setValue(tmp);
413 DynParaLoop::TypeOfNode DynParaLoop::getIdentityOfNotifyerNode(const Node *node, unsigned& id)
415 vector<Node *>::iterator iter;
417 for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++,id++)
421 for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++,id++)
425 for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++,id++)
427 return FINALIZE_NODE;
430 void DynParaLoop::setWeight(double loopWeight)
433 throw Exception("DynParaLoop::setWeight : invalid input value !");
434 _loopWeight=loopWeight;
437 ComplexWeight* DynParaLoop::getWeight()
440 _weight.setLoopWeight(_loopWeight, _node->getMaxLevelOfParallelism()); // not done in setWeight because _node can be null at that time
444 bool DynParaLoop::isMultiplicitySpecified(unsigned& value) const
446 return _nbOfBranches->isMultiplicitySpecified(value);
449 void DynParaLoop::forceMultiplicity(unsigned value)
451 _nbOfBranches->forceMultiplicity(value);
454 void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
456 string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
457 if(typeOfPortInstance!=InputPort::NAME)
458 throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop is not possible");
461 void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
463 std::string linkName("(");
464 linkName += port.first->getName()+" to "+finalTarget->getName()+")";
466 if(isInMyDescendance(port.first->getNode())==_initNode)
467 throw Exception(std::string("Illegal link within a parallel loop: \
468 a link starting from the init node can't leave the scope of the loop.")
472 if(isInMyDescendance(port.first->getNode())==_finalizeNode)
473 throw Exception(std::string("Illegal link within a parallel loop: \
474 an output port of the finalize node can't be linked.")
477 if(port.first==&_splittedPort)
478 throw Exception(std::string("Illegal link within a parallel loop: \
479 the 'evalSamples' port must be linked within the scope of the loop.")
483 void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
485 const char what[]="DynParaLoop::checkCFLinks : internal error.";
486 //First dealing checkCFLinks forwarding...
487 if(isInMyDescendance(end->getNode())==0)//no chance that _splittedPort is in starts due to buildDelegate.
488 solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
490 {//no forwarding here.
492 throw Exception(what);
493 //ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled.
494 if(alreadyFed==FREE_ST)
496 else if(alreadyFed==FED_ST)
497 {//Shame ! splittedPort fills a port already fed...
498 info.pushInfoLink(*(starts.begin()),end,I_USELESS);
504 * \param start : start port
505 * \param end : end port
506 * \param cross indicates if start -> end link is a DS link behind.
507 * \param fw out parameter.
508 * \param fwCross out parameter storing links where a cross has been detected.
509 * \param bw out parameter where backward links are stored.
510 * \param info : collected information
512 void DynParaLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
513 std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
514 std::vector<OutPort *>& fwCross,
515 std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
516 LinkInfo& info) const
518 fw[(ComposedNode *)this].push_back(start);
521 void DynParaLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
522 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd)
524 ComposedNode::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
525 Node * startNode = isInMyDescendance(start->getNode());
526 Node * endNode = isInMyDescendance(end->getNode());
527 std::string linkName("(");
528 linkName += start->getName()+" to "+end->getName()+")";
530 if(start == &_splittedPort && endNode != _node)
531 throw Exception(std::string("Illegal link within a parallel loop: \
532 the 'evalSamples' port can only be connected to the working node of the loop.")
535 if(_finalizeNode && _finalizeNode == startNode)
536 throw Exception(std::string("Illegal link within a parallel loop: \
537 the finalize node can't be the origin of a link.")
540 if(_initNode && _node == startNode && _initNode == endNode)
541 throw Exception(std::string("Illegal link within a parallel loop: \
542 can't make a link from the working node to the init node.")
545 if(_finalizeNode && _node == startNode && _finalizeNode == endNode)
546 throw Exception(std::string("Illegal link within a parallel loop: \
547 can't make a link from the working node to the finalize node.")
552 * \note : For a given name 'name' of port in absolute form from this, returns the corresponding InputPort
553 * instance of the port for the branch # 'branchNb'.
554 * The port can be part of _node or _initNode if it exists (if 'initNodeAdmitted' is true).
555 * \b WARNING : no check performed on 'branchNb' value to see if it is compatible with size of '_execNodes'.
556 * This method is called to dispatch value on each InputPort linked to this->._splitterNode._splittedPort
558 InputPort *DynParaLoop::getDynInputPortByAbsName(int branchNb, const std::string& name, bool initNodeAdmitted)
560 string portName, nodeName;
561 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true);
562 Node *staticChild = getChildByName(nodeName);
563 Node *desc=isInMyDescendance(staticChild);
566 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
567 return _execNodes[branchNb]->getInputPort(portName);
569 else if(desc==_initNode)
572 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
573 return _execInitNodes[branchNb]->getInputPort(portName);
578 void DynParaLoop::checkBasicConsistency() const
580 DEBTRACE("DynParaLoop::checkBasicConsistency");
581 ComposedNode::checkBasicConsistency();
583 throw Exception("For a dynamic loop, internal node is mandatory");
586 std::string DynParaLoop::getErrorReport()
588 DEBTRACE("DynParaLoop::getErrorReport: " << getName() << " " << _state);
589 YACS::StatesForNode effectiveState=getEffectiveState();
591 if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
594 std::string report="<error node= " + getName();
595 switch(effectiveState)
598 report=report+" state= INVALID";
601 report=report+" state= ERROR";
604 report=report+" state= FAILED";
609 report=report + ">\n" ;
610 if(_errorDetails != "")
611 report=report+_errorDetails+"\n";
613 if(_execNodes.empty())
616 list<Node *> constituents=edGetDirectDescendants();
617 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
619 std::string rep=(*iter)->getErrorReport();
622 report=report+rep+"\n";
629 for(vector<Node *>::iterator iter=_execInitNodes.begin();iter!=_execInitNodes.end();iter++)
631 std::string rep=(*iter)->getErrorReport();
634 report=report+rep+"\n";
637 for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++)
641 std::string rep=(*iter)->getErrorReport();
644 report=report+rep+"\n";
648 for(vector<Node *>::iterator iter=_execFinalizeNodes.begin();iter!=_execFinalizeNodes.end();iter++)
650 std::string rep=(*iter)->getErrorReport();
653 report=report+rep+"\n";
658 report=report+"</error>";
662 void DynParaLoop::forwardExecStateToOriginalBody(Node *execNode)
665 Node * origNode = NULL;
666 switch (getIdentityOfNotifyerNode(execNode,id))
670 origNode = _initNode;
680 origNode = _finalizeNode;
687 YASSERT(origNode != NULL)
688 origNode->setState(execNode->getState());
689 origNode->setErrorDetails(execNode->getErrorDetails());
691 ComposedNode* compNode = dynamic_cast<ComposedNode*>(origNode);
692 ComposedNode* compNodeExe = dynamic_cast<ComposedNode*>(execNode);
693 if (compNode && compNodeExe)
695 list<Node *> aChldn = compNodeExe->getAllRecursiveConstituents();
696 list<Node *>::iterator iter=aChldn.begin();
697 for(;iter!=aChldn.end();iter++)
699 Node* node=compNode->getChildByName(compNodeExe->getChildName(*iter));
700 node->setState((*iter)->getState());
701 node->setErrorDetails((*iter)->getErrorDetails());
706 //! Method used to notify the node that a child node has failed
708 * Update the current state and return the change state
710 * \param node : the child node that has failed
711 * \return the state change
713 YACS::Event DynParaLoop::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
715 DEBTRACE("DynParaLoop::updateStateOnFailedEventFrom " << node->getName());
716 setState(YACS::FAILED);
717 forwardExecStateToOriginalBody(node);
719 switch (getIdentityOfNotifyerNode(node,id))
723 _node->setState(YACS::FAILED);
724 if (_finalizeNode != NULL) _finalizeNode->setState(YACS::FAILED);
729 if (_finalizeNode != NULL) _finalizeNode->setState(YACS::FAILED);
736 //! Clone nodes and make their placement consistent with the placement of the original ones.
738 * For instance, if two original nodes are placed on a component comp1 in a container cont1
739 * and a third one is placed on a component comp2 in the container cont1, the clones of the two
740 * first nodes will be placed on a component comp3 in a container cont2 and the third clone
741 * will be placed on a component comp4 in the container cont2.
743 vector<Node *> DynParaLoop::cloneAndPlaceNodesCoherently(const vector<Node *> & origNodes)
745 DEBTRACE("Begin cloneAndPlaceNodesCoherently")
746 vector<Node *> clones;
747 DeploymentTree treeToDup;
748 vector<list<ElementaryNode *> > origElemNodeList;
749 for (int i=0 ; i<origNodes.size() ; i++)
751 DEBTRACE("Cloning node " << i)
752 if (origNodes[i] == NULL)
754 DEBTRACE("Cloning node " << i << ", NULL" )
755 clones.push_back(NULL);
756 origElemNodeList.push_back(list<ElementaryNode *>());
760 DEBTRACE("Cloning node " << i << "," << origNodes[i]->getName())
761 clones.push_back(origNodes[i]->simpleClone(this, false));
762 list<ElementaryNode *> tasks = origNodes[i]->getRecursiveConstituents();
763 origElemNodeList.push_back(tasks);
764 for (list< ElementaryNode *>::iterator iter=tasks.begin() ; iter!=tasks.end() ; iter++)
765 treeToDup.appendTask(*iter, (*iter)->getDynClonerIfExists(this));
769 // Build the links between clones.
770 // Only the links starting from initNode are possible.
773 std::vector< std::pair<OutPort *, InPort *> > outLinks = _initNode->getSetOfLinksLeavingCurrentScope();
774 std::vector< std::pair<OutPort *, InPort *> >::const_iterator it;
775 for(it=outLinks.begin(); it!=outLinks.end(); it++)
777 OutPort *startPort = it->first;
778 InPort *endPort = it->second;
779 Node* destNode = isInMyDescendance(endPort->getNode());
780 if(destNode == _node)
781 edAddLink(clones[0]->getOutPort(startPort->getName()),
782 clones[1]->getInPort(endPort->getName()));
783 if(destNode == _finalizeNode)
784 edAddLink(clones[0]->getOutPort(startPort->getName()),
785 clones[2]->getInPort(endPort->getName()));
789 DEBTRACE("Placing nodes...")
790 vector<Container *> conts=treeToDup.getAllContainers();
792 //iterate on all containers
793 for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
795 DEBTRACE("Container " << ((*iterCt)?(*iterCt)->getName():"NULL"))
796 vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
797 Container *contCloned=0;
799 contCloned=(*iterCt)->clone();
801 //iterate on all component instances linked to the container
802 for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
804 DEBTRACE("Component " << (*iterCp)->getCompoName())
805 vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
806 ComponentInstance *curCloned=(*iterCp)->clone();
807 DEBTRACE("Assign container " << (*iterCp)->getCompoName())
808 curCloned->setContainer(contCloned);
809 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
811 DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
813 ElementaryNode * origElemNode = NULL;
814 for (i=0 ; i<origNodes.size() ; i++)
815 if (origNodes[i] != NULL)
817 DEBTRACE("Looking in original node " << i)
818 list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
819 origElemNodeList[i].end(),
820 (ElementaryNode *)(*iterT));
821 if (res != origElemNodeList[i].end()) {
827 YASSERT(origElemNode != NULL)
828 DEBTRACE("Found task in node " << i)
829 ServiceNode * nodeC = NULL;
830 if (origNodes[i] == origElemNode)
831 nodeC = (ServiceNode *)clones[i];
834 string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
835 nodeC = (ServiceNode *)clones[i]->getChildByName(childName);
837 DEBTRACE("Assign component: " << (*iterCp)->getCompoName() << "," << nodeC->getName())
838 nodeC->setComponent(curCloned);
840 curCloned->decrRef();
843 // iterate on all tasks linked to the container
844 vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
845 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
847 DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
849 ElementaryNode * origElemNode = NULL;
850 for (i=0 ; i<origNodes.size() ; i++)
851 if (origNodes[i] != NULL)
853 DEBTRACE("Looking in original node " << i)
854 list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
855 origElemNodeList[i].end(),
856 (ElementaryNode *)(*iterT));
857 if (res != origElemNodeList[i].end())
863 YASSERT(origElemNode != NULL)
864 DEBTRACE("Found task in node " << i)
865 InlineFuncNode * nodeC = NULL;
866 if (origNodes[i] == origElemNode)
868 nodeC = (InlineFuncNode *)clones[i];
872 string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
873 nodeC = (InlineFuncNode *)clones[i]->getChildByName(childName);
875 DEBTRACE("Assign container " << nodeC->getName() << "," << contCloned->getName())
876 nodeC->setContainer(contCloned);
879 // ended with current container
881 contCloned->decrRef();
884 DEBTRACE("End cloneAndPlaceNodesCoherently")
888 void DynParaLoop::accept(Visitor *visitor)
890 visitor->visitDynParaLoop(this);
893 Node * DynParaLoop::getInitNode()
898 Node * DynParaLoop::getExecNode()
903 Node * DynParaLoop::getFinalizeNode()
905 return _finalizeNode;
908 int DynParaLoop::getMaxLevelOfParallelism() const
910 return _nbOfBranches->getIntValue() * _node->getMaxLevelOfParallelism();
913 void DynParaLoop::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
915 YACS::BASES::AutoRefCnt<PartDefinition> pd2(pd->copy());
918 _node->partitionRegardingDPL(pd,zeMap);
921 void DynParaLoop::shutdown(int level)
926 std::vector<Node *>::iterator iter;
927 for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
928 (*iter)->shutdown(level);
929 for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
930 (*iter)->shutdown(level);
931 for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
932 (*iter)->shutdown(level);