Version: 8.3.0
DynParaLoop.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 
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"
29 
30 #include <list>
31 #include <vector>
32 
33 //#define _DEVDEBUG_
34 #include "YacsTrace.hxx"
35 
36 using namespace std;
37 using namespace YACS::ENGINE;
38 
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
41 
42 const char DynParaLoop::NAME_OF_NUMBER_OF_BRANCHES[]="nbBranches";
43 
44 DynParaLoop::DynParaLoop(const std::string& name, TypeCode *typeOfDataSplitted)
45  : ComposedNode(name),_node(0),_initNode(0),_finalizeNode(0),_nbOfEltConsumed(0),
46  _nbOfBranches(NAME_OF_NUMBER_OF_BRANCHES,this,Runtime::_tc_int),
47  _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
48 {
49 }
50 
52 {
53  delete _node;
54  delete _initNode;
55  delete _finalizeNode;
56 }
57 
58 DynParaLoop::DynParaLoop(const DynParaLoop& other, ComposedNode *father, bool editionOnly)
59  : ComposedNode(other,father), _nbOfBranches(other._nbOfBranches,this),
60  _splittedPort(other._splittedPort,this), _node(0), _initNode(0), _finalizeNode(0),
61  _nbOfEltConsumed(0),_initializingCounter(0),_unfinishedCounter(0),_failedCounter(0)
62 {
63  if(other._node)
64  _node=other._node->clone(this,editionOnly);
65  if(other._initNode)
66  _initNode=other._initNode->clone(this,editionOnly);
67  if(other._finalizeNode)
68  _finalizeNode = other._finalizeNode->clone(this,editionOnly);
69  const AnyOutputPort& startOfLinksToReproduce=other._splittedPort;
70  set<InPort *> endsOfLinksToReproduce=startOfLinksToReproduce.edSetInPort();
71  for(set<InPort *>::iterator iter=endsOfLinksToReproduce.begin();iter!=endsOfLinksToReproduce.end();iter++)
73 }
74 
76 {
77  return checkConsistencyAndSetNode(_node, node);
78 }
79 
82 {
83  if (node == NULL || nodeToReplace == node)
84  return 0;
85  if (node->_father)
86  throw Exception(string("Can't set node: node ") + node->getName() + " is not orphan.");
87  if (_node && _node != nodeToReplace && _node->getName() == node->getName())
88  throw Exception(string("Can't set node: node ") + node->getName() +
89  " has the same name than exec node already in " + _name + ".");
90  if (_initNode && _initNode != nodeToReplace && _initNode->getName() == node->getName())
91  throw Exception(string("Can't set node: node ") + node->getName() +
92  " has the same name than init node already in " + _name + ".");
93  if (_finalizeNode && _finalizeNode != nodeToReplace && _finalizeNode->getName() == node->getName())
94  throw Exception(string("Can't set node: node ") + node->getName() +
95  " has the same name than finalize node already in " + _name + ".");
97  ComposedNode::edRemoveChild(nodeToReplace);
98  Node * ret = nodeToReplace;
99  nodeToReplace = node;
100  nodeToReplace->_father = this;
101  // set _modified flag so that edUpdateState can refresh state
102  modified();
103  return ret;
104 }
105 
106 void DynParaLoop::init(bool start)
107 {
108  ComposedNode::init(start);
109  if(!_node)
110  {
111  string what("DynParaLoop::init : no node specified for ForEachLoop with name "); what +=_name;
112  throw Exception(what);
113  }
114  _node->init(start);
115  if (_initNode) _initNode->init(start);
116  if (_finalizeNode) _finalizeNode->init(start);
117  _nbOfBranches.exInit(start);
120  _failedCounter=0;
121 }
122 
124 {
126 }
127 
129 {
131 }
132 
134 
143 {
144  return edAddLink(start,end);
145 }
146 
148 {
150 }
151 
153 {
155 }
156 
163 {
164  if(_node)
165  {
166  for(std::vector<Node *>::const_iterator it=_execNodes.begin();it!=_execNodes.end();it++)
167  if(node==*it)
168  return std::distance(_execNodes.begin(),it);
169  }
170  if(_finalizeNode)
171  {
172  for(std::vector<Node *>::const_iterator it=_execFinalizeNodes.begin();it!=_execFinalizeNodes.end();it++)
173  if(node==*it)
174  return std::distance(_execFinalizeNodes.begin(),it);
175  }
176  if(_initNode)
177  {
178  for(std::vector<Node *>::const_iterator it=_execInitNodes.begin();it!=_execInitNodes.end();it++)
179  if(node==*it)
180  return std::distance(_execInitNodes.begin(),it);
181  }
182  return -1;
183 }
184 
185 std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
186 {
187  list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
188  ret.push_back((OutputPort *)&_splittedPort);
189  return ret;
190 }
191 
192 std::list<OutputPort *> DynParaLoop::getLocalOutputPorts() const
193 {
194  list<OutputPort *> ret=ComposedNode::getLocalOutputPorts();
195  ret.push_back((OutputPort *)&_splittedPort);
196  return ret;
197 }
198 
199 OutPort *DynParaLoop::getOutPort(const std::string& name) const throw(YACS::Exception)
200 {
201  if (name == NAME_OF_SPLITTED_SEQ_OUT || name == OLD_NAME_OF_SPLITTED_SEQ_OUT)
202  return (OutPort *)&_splittedPort;
203  return ComposedNode::getOutPort(name);
204 }
205 
206 
207 OutputPort *DynParaLoop::getOutputPort(const std::string& name) const throw(YACS::Exception)
208 {
209  if (name == NAME_OF_SPLITTED_SEQ_OUT || name == OLD_NAME_OF_SPLITTED_SEQ_OUT)
210  return (OutputPort *)&_splittedPort;
211  return ComposedNode::getOutputPort(name);
212 }
213 
215 {
216  return false;
217 }
218 
220 {
221  return removeNode(_node);
222 }
223 
226 {
227  if (!nodeToRemove)
228  return NULL;
229  ComposedNode::edRemoveChild(nodeToRemove);
230  Node * ret = nodeToRemove;
231  nodeToRemove = NULL;
232  modified();
233  return ret;
234 }
235 
237 {
238  return removeNode(_initNode);
239 }
240 
242 {
243  return removeNode(_finalizeNode);
244 }
245 
247 {
249  if(node==_node)
250  _node=0;
251  if(node==_initNode)
252  _initNode=0;
253  if(node==_finalizeNode)
254  _finalizeNode=0;
255  modified();
256 }
257 
259 {
260  return edSetNode(DISOWNnode);
261 }
262 
263 std::list<Node *> DynParaLoop::edGetDirectDescendants() const
264 {
265  list<Node *> ret;
266  if(_node)
267  ret.push_back(_node);
268  if(_initNode)
269  ret.push_back(_initNode);
270  if(_finalizeNode)
271  ret.push_back(_finalizeNode);
272  return ret;
273 }
274 
275 std::list<InputPort *> DynParaLoop::getSetOfInputPort() const
276 {
277  list<InputPort *> ret=ComposedNode::getSetOfInputPort();
278  ret.push_back((InputPort *)&_nbOfBranches);
279  return ret;
280 }
281 
282 InputPort *DynParaLoop::getInputPort(const std::string& name) const throw(YACS::Exception)
283 {
284  if(name==NAME_OF_NUMBER_OF_BRANCHES)
285  return (InputPort *)&_nbOfBranches;
286  return ComposedNode::getInputPort(name);
287 }
288 
289 std::list<InputPort *> DynParaLoop::getLocalInputPorts() const
290 {
291  list<InputPort *> ret=ComposedNode::getLocalInputPorts();
292  ret.push_back((InputPort *)&_nbOfBranches);
293  return ret;
294 }
295 
297 {
298  if(_execNodes.empty())
299  throw Exception("ForEachLoop::getNumberOfBranches : No branches created dynamically ! - ForEachLoop needs to run or to be runned to call getNumberOfBranches");
300  else
301  return _execNodes.size();
302 }
303 
304 Node *DynParaLoop::getChildByShortName(const std::string& name) const throw(YACS::Exception)
305 {
306  if (_node && name == _node->getName())
307  return _node;
308  if (_initNode && name == _initNode->getName())
309  return _initNode;
310  if (_finalizeNode && name == _finalizeNode->getName())
311  return _finalizeNode;
312  std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
313  throw Exception(what);
314 }
315 
316 Node *DynParaLoop::getChildByNameExec(const std::string& name, unsigned id) const throw(YACS::Exception)
317 {
318  if(id>=getNumberOfBranchesCreatedDyn())
319  throw Exception("ForEachLoop::getChildByNameExec : invalid id - too large compared with dynamically created branches.");
320  if (_node && name == _node->getName())
321  return _execNodes[id];
322  if (_initNode && name == _initNode->getName())
323  return _execInitNodes[id];
324  if (_finalizeNode && name == _finalizeNode->getName())
325  return _execFinalizeNodes[id];
326  std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
327  throw Exception(what);
328 }
329 
331 {
332  vector<Node *>::iterator iter;
333  for(iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
334  delete *iter;
335  _execNodes.clear();
336  for(iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
337  delete *iter;
338  _execInitNodes.clear();
339  for(iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
340  delete *iter;
341  _execFinalizeNodes.clear();
342 }
343 
349 {
350  set< InPort * > portsToSetVals=getAllInPortsComingFromOutsideOfCurrentScope();
351 
352  // This tweak is to fix problems with nested dynamic loops where links are not cloned properly
353  list<InPort *> temp = getSetOfInPort();
354  for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
355  {
356  if ((*iter2)->edSetOutPort().size() == 1 && *(*iter2)->edSetOutPort().begin() == NULL)
357  {
358  portsToSetVals.insert(*iter2);
359  }
360  }
361 
362  // local input ports are not candidates for dynamically duplicated inport.
363  list<InputPort *> localPorts = getLocalInputPorts();
364  for(list<InputPort *>::iterator iter = localPorts.begin() ; iter != localPorts.end() ; iter++)
365  portsToSetVals.erase(*iter);
366  for(set< InPort * >::iterator iter=portsToSetVals.begin();iter!=portsToSetVals.end();iter++)
367  {
368  InputPort *curPortCasted=(InputPort *) *iter;//Cast granted by ForEachLoop::buildDelegateOf(InPort)
369  void *val=curPortCasted->get();
370  InputPort *portToSet=getDynInputPortByAbsName(branchNb,getInPortName(*iter),true);
371  if(portToSet)//portToSet==0 in case of portToSet==_splitterNode._dataPortToDispatch of ForEach
372  {
373  portToSet->put((const void *)val);
374  portToSet->edNotifyReferencedBy(0);//This is to indicate that somewhere somebody deals with this inputport
375  //even if no direct physical link exists. This exclusively for _execNodes[branchNb]::init on the next turn of loop.
376  }
377  }
378 }
379 
380 void DynParaLoop::putValueOnBranch(Any *val, unsigned branchId, bool first)
381 {
382  bool isDispatched = false;
383  set<InPort *> inPrtLkdWthSplttdPrt=_splittedPort.edSetInPort();
384  for(set<InPort *>::iterator iter=inPrtLkdWthSplttdPrt.begin();iter!=inPrtLkdWthSplttdPrt.end();iter++)
385  {
386  std::string portNameOnCurPrt=getPortName(*iter);
387  InputPort *portOnGivenBranch=getDynInputPortByAbsName(branchId,portNameOnCurPrt,first);//Cast granted because impossible to have cross protocol with _splittedPort
388  //see OptimizerLoop::buildDelegateOf
389  if(portOnGivenBranch)
390  {
391  if(first)
392  portOnGivenBranch->edNotifyReferencedBy(0);
393  InputPort *traducer=getRuntime()->adapt(portOnGivenBranch,
395  traducer->put((const void *)val);
396  isDispatched = true;
397  if(traducer!=portOnGivenBranch)
398  delete traducer;
399  }
400  }
401  if ( isDispatched )
402  {
403  Any *tmp=val->clone();
404  _splittedPort.setValue(tmp);
405  tmp->decrRef();
406  }
407 }
408 
410 {
411  vector<Node *>::iterator iter;
412  id=0;
413  for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++,id++)
414  if (*iter==node)
415  return WORK_NODE;
416  id=0;
417  for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++,id++)
418  if (*iter==node)
419  return INIT_NODE;
420  id=0;
421  for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++,id++)
422  if (*iter==node)
423  return FINALIZE_NODE;
424 }
425 
426 bool DynParaLoop::isMultiplicitySpecified(unsigned& value) const
427 {
430  {
431  value=_nbOfBranches.getIntValue();
432  return true;
433  }
434  return false;
435 }
436 
437 void DynParaLoop::forceMultiplicity(unsigned value)
438 {
440  _nbOfBranches.edInit((int)value);
441 }
442 
443 void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
444 {
445  string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
446  if(typeOfPortInstance!=InputPort::NAME)
447  throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop is not possible");
448 }
449 
450 void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
451 {
452  std::string linkName("(");
453  linkName += port.first->getName()+" to "+finalTarget->getName()+")";
454  if(_initNode)
455  if(isInMyDescendance(port.first->getNode())==_initNode)
456  throw Exception(std::string("Illegal link within a parallel loop: \
457 a link starting from the init node can't leave the scope of the loop.")
458  + linkName);
459 
460  if(_finalizeNode)
461  if(isInMyDescendance(port.first->getNode())==_finalizeNode)
462  throw Exception(std::string("Illegal link within a parallel loop: \
463 an output port of the finalize node can't be linked.")
464  + linkName);
465 
466  if(port.first==&_splittedPort)
467  throw Exception(std::string("Illegal link within a parallel loop: \
468 the 'evalSamples' port must be linked within the scope of the loop.")
469  + linkName);
470 }
471 
472 void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
473 {
474  const char what[]="DynParaLoop::checkCFLinks : internal error.";
475  //First dealing checkCFLinks forwarding...
476  if(isInMyDescendance(end->getNode())==0)//no chance that _splittedPort is in starts due to buildDelegate.
477  solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
478  else
479  {//no forwarding here.
480  if(starts.size()!=1)
481  throw Exception(what);
482  //ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled.
483  if(alreadyFed==FREE_ST)
484  alreadyFed=FED_ST;
485  else if(alreadyFed==FED_ST)
486  {//Shame ! splittedPort fills a port already fed...
487  info.pushInfoLink(*(starts.begin()),end,I_USELESS);
488  }
489  }
490 }
491 
501 void DynParaLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
502  std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
503  std::vector<OutPort *>& fwCross,
504  std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
505  LinkInfo& info) const
506 {
507  fw[(ComposedNode *)this].push_back(start);
508 }
509 
510 void DynParaLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
511  InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
512 {
513  ComposedNode::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
514  Node * startNode = isInMyDescendance(start->getNode());
515  Node * endNode = isInMyDescendance(end->getNode());
516  std::string linkName("(");
517  linkName += start->getName()+" to "+end->getName()+")";
518 
519  if(start == &_splittedPort && endNode != _node)
520  throw Exception(std::string("Illegal link within a parallel loop: \
521 the 'evalSamples' port can only be connected to the working node of the loop.")
522  + linkName);
523 
524  if(_finalizeNode && _finalizeNode == startNode)
525  throw Exception(std::string("Illegal link within a parallel loop: \
526 the finalize node can't be the origin of a link.")
527  + linkName);
528 
529  if(_initNode && _node == startNode && _initNode == endNode)
530  throw Exception(std::string("Illegal link within a parallel loop: \
531 can't make a link from the working node to the init node.")
532  + linkName);
533 
534  if(_finalizeNode && _node == startNode && _finalizeNode == endNode)
535  throw Exception(std::string("Illegal link within a parallel loop: \
536 can't make a link from the working node to the finalize node.")
537  + linkName);
538 }
539 
547 InputPort *DynParaLoop::getDynInputPortByAbsName(int branchNb, const std::string& name, bool initNodeAdmitted)
548 {
549  string portName, nodeName;
550  splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true);
551  Node *staticChild = getChildByName(nodeName);
552  Node *desc=isInMyDescendance(staticChild);
553  if(desc==_node)
554  {
555  splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
556  return _execNodes[branchNb]->getInputPort(portName);
557  }
558  else if(desc==_initNode)
559  if(initNodeAdmitted)
560  {
561  splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
562  return _execInitNodes[branchNb]->getInputPort(portName);
563  }
564  return 0;
565 }
566 
568 {
569  DEBTRACE("DynParaLoop::checkBasicConsistency");
571  if(!_node)
572  throw Exception("For a dynamic loop, internal node is mandatory");
573 }
574 
576 {
577  DEBTRACE("DynParaLoop::getErrorReport: " << getName() << " " << _state);
578  YACS::StatesForNode effectiveState=getEffectiveState();
579 
580  if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
581  return "";
582 
583  std::string report="<error node= " + getName();
584  switch(effectiveState)
585  {
586  case YACS::INVALID:
587  report=report+" state= INVALID";
588  break;
589  case YACS::ERROR:
590  report=report+" state= ERROR";
591  break;
592  case YACS::FAILED:
593  report=report+" state= FAILED";
594  break;
595  default:
596  break;
597  }
598  report=report + ">\n" ;
599  if(_errorDetails != "")
600  report=report+_errorDetails+"\n";
601 
602  if(_execNodes.empty())
603  {
604  // edition node
605  list<Node *> constituents=edGetDirectDescendants();
606  for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
607  {
608  std::string rep=(*iter)->getErrorReport();
609  if(rep != "")
610  {
611  report=report+rep+"\n";
612  }
613  }
614  }
615  else
616  {
617  // execution nodes
618  for(vector<Node *>::iterator iter=_execInitNodes.begin();iter!=_execInitNodes.end();iter++)
619  {
620  std::string rep=(*iter)->getErrorReport();
621  if(rep != "")
622  {
623  report=report+rep+"\n";
624  }
625  }
626  for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++)
627  {
628  std::string rep=(*iter)->getErrorReport();
629  if(rep != "")
630  {
631  report=report+rep+"\n";
632  }
633  }
634  for(vector<Node *>::iterator iter=_execFinalizeNodes.begin();iter!=_execFinalizeNodes.end();iter++)
635  {
636  std::string rep=(*iter)->getErrorReport();
637  if(rep != "")
638  {
639  report=report+rep+"\n";
640  }
641  }
642  }
643 
644  report=report+"</error>";
645  return report;
646 }
647 
649 {
650  unsigned int id;
651  Node * origNode = NULL;
652  switch (getIdentityOfNotifyerNode(execNode,id))
653  {
654  case INIT_NODE:
655  {
656  origNode = _initNode;
657  break;
658  }
659  case WORK_NODE:
660  {
661  origNode = _node;
662  break;
663  }
664  case FINALIZE_NODE:
665  {
666  origNode = _finalizeNode;
667  break;
668  }
669  default:
670  YASSERT(false)
671  }
672 
673  YASSERT(origNode != NULL)
674  origNode->setState(execNode->getState());
675  origNode->setErrorDetails(execNode->getErrorDetails());
676 
677  ComposedNode* compNode = dynamic_cast<ComposedNode*>(origNode);
678  ComposedNode* compNodeExe = dynamic_cast<ComposedNode*>(execNode);
679  if (compNode && compNodeExe)
680  {
681  list<Node *> aChldn = compNodeExe->getAllRecursiveConstituents();
682  list<Node *>::iterator iter=aChldn.begin();
683  for(;iter!=aChldn.end();iter++)
684  {
685  Node* node=compNode->getChildByName(compNodeExe->getChildName(*iter));
686  node->setState((*iter)->getState());
687  node->setErrorDetails((*iter)->getErrorDetails());
688  }
689  }
690 }
691 
693 
700 {
701  DEBTRACE("DynParaLoop::updateStateOnFailedEventFrom " << node->getName());
704  unsigned int id;
705  switch (getIdentityOfNotifyerNode(node,id))
706  {
707  case INIT_NODE:
708  {
711  break;
712  }
713  case WORK_NODE:
714  {
716  break;
717  }
718  }
719  return YACS::ABORT;
720 }
721 
723 
729 vector<Node *> DynParaLoop::cloneAndPlaceNodesCoherently(const vector<Node *> & origNodes)
730 {
731  DEBTRACE("Begin cloneAndPlaceNodesCoherently")
732  vector<Node *> clones;
733  DeploymentTree treeToDup;
734  vector<list<ElementaryNode *> > origElemNodeList;
735  for (int i=0 ; i<origNodes.size() ; i++)
736  {
737  DEBTRACE("Cloning node " << i)
738  if (origNodes[i] == NULL)
739  {
740  DEBTRACE("Cloning node " << i << ", NULL" )
741  clones.push_back(NULL);
742  origElemNodeList.push_back(list<ElementaryNode *>());
743  }
744  else
745  {
746  DEBTRACE("Cloning node " << i << "," << origNodes[i]->getName())
747  clones.push_back(origNodes[i]->simpleClone(this, false));
748  list<ElementaryNode *> tasks = origNodes[i]->getRecursiveConstituents();
749  origElemNodeList.push_back(tasks);
750  for (list< ElementaryNode *>::iterator iter=tasks.begin() ; iter!=tasks.end() ; iter++)
751  treeToDup.appendTask(*iter, (*iter)->getDynClonerIfExists(this));
752  }
753  }
754 
755  // Build the links between clones.
756  // Only the links starting from initNode are possible.
757  if(_initNode)
758  {
759  std::vector< std::pair<OutPort *, InPort *> > outLinks = _initNode->getSetOfLinksLeavingCurrentScope();
760  std::vector< std::pair<OutPort *, InPort *> >::const_iterator it;
761  for(it=outLinks.begin(); it!=outLinks.end(); it++)
762  {
763  OutPort *startPort = it->first;
764  InPort *endPort = it->second;
765  Node* destNode = isInMyDescendance(endPort->getNode());
766  if(destNode == _node)
767  edAddLink(clones[0]->getOutPort(startPort->getName()),
768  clones[1]->getInPort(endPort->getName()));
769  if(destNode == _finalizeNode)
770  edAddLink(clones[0]->getOutPort(startPort->getName()),
771  clones[2]->getInPort(endPort->getName()));
772  }
773  }
774 
775  DEBTRACE("Placing nodes...")
776  vector<Container *> conts=treeToDup.getAllContainers();
777 
778  //iterate on all containers
779  for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
780  {
781  DEBTRACE("Container " << ((*iterCt)?(*iterCt)->getName():"NULL"))
782  vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
783  Container *contCloned=0;
784  if((*iterCt))
785  contCloned=(*iterCt)->clone();
786 
787  //iterate on all component instances linked to the container
788  for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
789  {
790  DEBTRACE("Component " << (*iterCp)->getCompoName())
791  vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
792  ComponentInstance *curCloned=(*iterCp)->clone();
793  DEBTRACE("Assign container " << (*iterCp)->getCompoName())
794  curCloned->setContainer(contCloned);
795  for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
796  {
797  DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
798  int i = 0;
799  ElementaryNode * origElemNode = NULL;
800  for (i=0 ; i<origNodes.size() ; i++)
801  if (origNodes[i] != NULL)
802  {
803  DEBTRACE("Looking in original node " << i)
804  list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
805  origElemNodeList[i].end(),
806  (ElementaryNode *)(*iterT));
807  if (res != origElemNodeList[i].end()) {
808  origElemNode = *res;
809  break;
810  }
811  }
812 
813  YASSERT(origElemNode != NULL)
814  DEBTRACE("Found task in node " << i)
815  ServiceNode * nodeC = NULL;
816  if (origNodes[i] == origElemNode)
817  nodeC = (ServiceNode *)clones[i];
818  else
819  {
820  string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
821  nodeC = (ServiceNode *)clones[i]->getChildByName(childName);
822  }
823  DEBTRACE("Assign component: " << (*iterCp)->getCompoName() << "," << nodeC->getName())
824  nodeC->setComponent(curCloned);
825  }
826  curCloned->decrRef();
827  }
828 
829  // iterate on all tasks linked to the container
830  vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
831  for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
832  {
833  DEBTRACE("Task " << ((ElementaryNode *)(*iterT))->getName())
834  int i = 0;
835  ElementaryNode * origElemNode = NULL;
836  for (i=0 ; i<origNodes.size() ; i++)
837  if (origNodes[i] != NULL)
838  {
839  DEBTRACE("Looking in original node " << i)
840  list<ElementaryNode *>::iterator res=find(origElemNodeList[i].begin(),
841  origElemNodeList[i].end(),
842  (ElementaryNode *)(*iterT));
843  if (res != origElemNodeList[i].end())
844  {
845  origElemNode = *res;
846  break;
847  }
848  }
849  YASSERT(origElemNode != NULL)
850  DEBTRACE("Found task in node " << i)
851  InlineFuncNode * nodeC = NULL;
852  if (origNodes[i] == origElemNode)
853  {
854  nodeC = (InlineFuncNode *)clones[i];
855  }
856  else
857  {
858  string childName = ((ComposedNode *)origNodes[i])->getChildName(origElemNode);
859  nodeC = (InlineFuncNode *)clones[i]->getChildByName(childName);
860  }
861  DEBTRACE("Assign container " << nodeC->getName() << "," << contCloned->getName())
862  nodeC->setContainer(contCloned);
863  }
864 
865  // ended with current container
866  if(contCloned)
867  contCloned->decrRef();
868  }
869 
870  DEBTRACE("End cloneAndPlaceNodesCoherently")
871  return clones;
872 }
873 
875 {
876  visitor->visitDynParaLoop(this);
877 }
878 
880 {
881  return _initNode;
882 }
883 
885 {
886  return _node;
887 }
888 
890 {
891  return _finalizeNode;
892 }
893 
895 {
897 }
898 
899 void DynParaLoop::shutdown(int level)
900 {
901  if(level==0)return;
902  if(!_node) return;
903 
904  std::vector<Node *>::iterator iter;
905  for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
906  (*iter)->shutdown(level);
907  for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
908  (*iter)->shutdown(level);
909  for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
910  (*iter)->shutdown(level);
911 }