1 // Copyright (C) 2006-2014 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 "ForEachLoop.hxx"
21 #include "TypeCode.hxx"
22 #include "Visitor.hxx"
23 #include "ComposedNode.hxx"
28 #include "YacsTrace.hxx"
30 using namespace YACS::ENGINE;
33 /*! \class YACS::ENGINE::ForEachLoop
34 * \brief Loop node for parametric calculation
39 const char FakeNodeForForEachLoop::NAME[]="thisIsAFakeNode";
41 const char SplitterNode::NAME_OF_SEQUENCE_INPUT[]="SmplsCollection";
43 const char ForEachLoop::NAME_OF_SPLITTERNODE[]="splitter";
45 const int ForEachLoop::NOT_RUNNING_BRANCH_ID=-1;
47 InterceptorInputPort::InterceptorInputPort(const std::string& name, Node *node, TypeCode* type):AnyInputPort(name,node,type),
48 DataPort(name,node,type),Port(node),
53 InterceptorInputPort::InterceptorInputPort(const InterceptorInputPort& other, Node *newHelder):AnyInputPort(other,newHelder),DataPort(other,newHelder),
54 Port(other,newHelder),
59 void InterceptorInputPort::getAllRepresentants(std::set<InPort *>& repr) const
61 set<InPort *> ports=_repr->edSetInPort();
62 for(set<InPort *>::iterator iter=ports.begin();iter!=ports.end();iter++)
63 (*iter)->getAllRepresentants(repr);
66 InputPort *InterceptorInputPort::clone(Node *newHelder) const
68 return new InterceptorInputPort(*this,newHelder);
71 void InterceptorInputPort::setRepr(AnySplitOutputPort *repr)
76 bool AnySplitOutputPort::decrRef()
81 void AnySplitOutputPort::incrRef() const
86 AnySplitOutputPort::AnySplitOutputPort(const std::string& name, Node *node, TypeCode *type):OutputPort(name,node,type),
87 DataPort(name,node,type),Port(node),
88 _repr(0),_intercptr(0),_cnt(1)
92 AnySplitOutputPort::AnySplitOutputPort(const AnySplitOutputPort& other, Node *newHelder):OutputPort(other,newHelder),
93 DataPort(other,newHelder),
94 Port(other,newHelder),
95 _repr(0),_intercptr(0),_cnt(1)
99 bool AnySplitOutputPort::addInPort(InPort *inPort) throw(YACS::Exception)
101 bool ret=OutputPort::addInPort(inPort);
103 _repr->addInPort(_intercptr);
107 void AnySplitOutputPort::getAllRepresented(std::set<OutPort *>& represented) const
110 OutPort::getAllRepresented(represented);
112 _repr->getAllRepresented(represented);
115 int AnySplitOutputPort::removeInPort(InPort *inPort, bool forward) throw(YACS::Exception)
117 bool ret=OutputPort::removeInPort(inPort,forward);
119 if(_setOfInputPort.empty())
120 _repr->removeInPort(_intercptr,forward);
124 void AnySplitOutputPort::addRepr(OutPort *repr, InterceptorInputPort *intercptr)
127 _intercptr=intercptr;
130 OutputPort *AnySplitOutputPort::clone(Node *newHelder) const
132 return new AnySplitOutputPort(*this,newHelder);
135 SeqAnyInputPort::SeqAnyInputPort(const std::string& name, Node *node, TypeCodeSeq* type):AnyInputPort(name,node,type),DataPort(name,node,type),Port(node)
140 SeqAnyInputPort::SeqAnyInputPort(const SeqAnyInputPort& other, Node *newHelder):AnyInputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder)
144 InputPort *SeqAnyInputPort::clone(Node *newHelder) const
146 return new SeqAnyInputPort(*this,newHelder);
149 unsigned SeqAnyInputPort::getNumberOfElements() const
151 const SequenceAny * valCsted=(const SequenceAny *) _value;
152 if (valCsted) return valCsted->size();
156 Any *SeqAnyInputPort::getValueAtRank(int i) const
158 const SequenceAny * valCsted=(const SequenceAny *) _value;
159 AnyPtr ret=(*valCsted)[i];
164 std::string SeqAnyInputPort::dump()
166 stringstream xmldump;
167 int nbElem = getNumberOfElements();
168 xmldump << "<value><array><data>" << endl;
169 for (int i = 0; i < nbElem; i++)
171 Any *val = getValueAtRank(i);
172 switch (val->getType()->kind())
175 xmldump << "<value><double>" << val->getDoubleValue() << "</double></value>" << endl;
178 xmldump << "<value><int>" << val->getIntValue() << "</int></value>" << endl;
181 xmldump << "<value><boolean>" << val->getBoolValue() << "</boolean></value>" << endl;
184 xmldump << "<value><string>" << val->getStringValue() << "</string></value>" << endl;
187 xmldump << "<value><objref>" << val->getStringValue() << "</objref></value>" << endl;
190 xmldump << "<value><error> NO_SERIALISATION_AVAILABLE </error></value>" << endl;
194 xmldump << "</data></array></value>" << endl;
195 return xmldump.str();
198 SplitterNode::SplitterNode(const std::string& name, TypeCode *typeOfData,
199 ForEachLoop *father):ElementaryNode(name),
200 _dataPortToDispatch(NAME_OF_SEQUENCE_INPUT,
201 this,(TypeCodeSeq *)TypeCode::sequenceTc("","",typeOfData))
206 SplitterNode::SplitterNode(const SplitterNode& other, ForEachLoop *father):ElementaryNode(other,father),
207 _dataPortToDispatch(other._dataPortToDispatch,this)
211 InputPort *SplitterNode::getInputPort(const std::string& name) const throw(YACS::Exception)
213 if(name==NAME_OF_SEQUENCE_INPUT)
214 return (InputPort *)&_dataPortToDispatch;
216 return ElementaryNode::getInputPort(name);
219 Node *SplitterNode::simpleClone(ComposedNode *father, bool editionOnly) const
221 return new SplitterNode(*this,(ForEachLoop *)father);
224 unsigned SplitterNode::getNumberOfElements() const
226 return _dataPortToDispatch.getNumberOfElements();
229 void SplitterNode::execute()
231 //Nothing : should never been called elsewhere big problem...
234 void SplitterNode::init(bool start)
236 ElementaryNode::init(start);
237 _dataPortToDispatch.exInit(start);
240 void SplitterNode::putSplittedValueOnRankTo(int rankInSeq, int branch, bool first)
242 Any *valueToDispatch=_dataPortToDispatch.getValueAtRank(rankInSeq);
243 ForEachLoop *fatherTyped=(ForEachLoop *)_father;
244 fatherTyped->putValueOnBranch(valueToDispatch,branch,first);
245 valueToDispatch->decrRef();
248 FakeNodeForForEachLoop::FakeNodeForForEachLoop(ForEachLoop *loop, bool normalFinish):ElementaryNode(NAME),
250 _normalFinish(normalFinish)
252 _state=YACS::TOACTIVATE;
253 _father=_loop->getFather();
256 FakeNodeForForEachLoop::FakeNodeForForEachLoop(const FakeNodeForForEachLoop& other):ElementaryNode(other),_loop(0),
261 Node *FakeNodeForForEachLoop::simpleClone(ComposedNode *father, bool editionOnly) const
263 return new FakeNodeForForEachLoop(*this);
266 void FakeNodeForForEachLoop::exForwardFailed()
268 _loop->exForwardFailed();
271 void FakeNodeForForEachLoop::exForwardFinished()
273 _loop->exForwardFinished();
276 void FakeNodeForForEachLoop::execute()
279 throw Exception("");//only to trigger ABORT on Executor
281 _loop->pushAllSequenceValues();
284 void FakeNodeForForEachLoop::aborted()
286 _loop->setState(YACS::ERROR);
289 void FakeNodeForForEachLoop::finished()
291 _loop->setState(YACS::DONE);
294 ForEachLoop::ForEachLoop(const std::string& name, TypeCode *typeOfDataSplitted):DynParaLoop(name,typeOfDataSplitted),
295 _splitterNode(NAME_OF_SPLITTERNODE,typeOfDataSplitted,this),
296 _execCurrentId(0),_nodeForSpecialCases(0),_currentIndex(0)
300 ForEachLoop::ForEachLoop(const ForEachLoop& other, ComposedNode *father, bool editionOnly):DynParaLoop(other,father,editionOnly),
301 _splitterNode(other._splitterNode,this),
302 _execCurrentId(0),_nodeForSpecialCases(0),_currentIndex(0)
306 for(vector<AnySplitOutputPort *>::const_iterator iter2=other._outGoingPorts.begin();iter2!=other._outGoingPorts.end();iter2++,i++)
308 AnySplitOutputPort *temp=new AnySplitOutputPort(*(*iter2),this);
309 InterceptorInputPort *interc=new InterceptorInputPort(*other._intecptrsForOutGoingPorts[i],this);
310 temp->addRepr(getOutPort((*iter2)->getName()),interc);
311 interc->setRepr(temp);
312 _outGoingPorts.push_back(temp);
313 _intecptrsForOutGoingPorts.push_back(interc);
317 Node *ForEachLoop::simpleClone(ComposedNode *father, bool editionOnly) const
319 return new ForEachLoop(*this,father,editionOnly);
322 ForEachLoop::~ForEachLoop()
325 for(vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
327 for(vector<InterceptorInputPort *>::iterator iter2=_intecptrsForOutGoingPorts.begin();iter2!=_intecptrsForOutGoingPorts.end();iter2++)
331 void ForEachLoop::init(bool start)
333 DynParaLoop::init(start);
334 _splitterNode.init(start);
341 void ForEachLoop::exUpdateState()
343 DEBTRACE("ForEachLoop::exUpdateState");
344 if(_state == YACS::DISABLED)
346 if(_inGate.exIsReady())
348 //internal graph update
350 int nbOfBr=_nbOfBranches.getIntValue();
351 int nbOfElts=_splitterNode.getNumberOfElements();
353 DEBTRACE("nbOfElts=" << nbOfElts);
354 DEBTRACE("nbOfBr=" << nbOfBr);
358 prepareSequenceValues(0);
359 delete _nodeForSpecialCases;
360 _nodeForSpecialCases=new FakeNodeForForEachLoop(this,true);
361 setState(YACS::ACTIVATED);
366 delete _nodeForSpecialCases;
367 _nodeForSpecialCases=new FakeNodeForForEachLoop(this,getAllOutPortsLeavingCurrentScope().empty());
368 setState(YACS::ACTIVATED);
373 _execNodes.resize(nbOfBr);
374 _execIds.resize(nbOfBr);
375 _execOutGoingPorts.resize(nbOfBr);
376 prepareSequenceValues(nbOfElts);
378 _execInitNodes.resize(nbOfBr);
379 _initializingCounter = 0;
381 _execFinalizeNodes.resize(nbOfBr);
383 vector<Node *> origNodes;
384 origNodes.push_back(_initNode);
385 origNodes.push_back(_node);
386 origNodes.push_back(_finalizeNode);
388 //Conversion exceptions can be thrown by createOutputOutOfScopeInterceptors
389 //so catch them to control errors
392 for(i=0;i<nbOfBr;i++)
394 DEBTRACE( "-------------- 1 " << i << " " << _execCurrentId);
395 _execIds[i]=_execCurrentId;
396 DEBTRACE( "-------------- 2" );
397 vector<Node *> clonedNodes = cloneAndPlaceNodesCoherently(origNodes);
399 _execInitNodes[i] = clonedNodes[0];
400 _execNodes[i] = clonedNodes[1];
402 _execFinalizeNodes[i] = clonedNodes[2];
403 DEBTRACE( "-------------- 4" );
404 prepareInputsFromOutOfScope(i);
405 DEBTRACE( "-------------- 5" );
406 createOutputOutOfScopeInterceptors(i);
407 DEBTRACE( "-------------- 6" );
408 _splitterNode.putSplittedValueOnRankTo(_execCurrentId++,i,true);
409 DEBTRACE( "-------------- 7" );
412 catch(YACS::Exception& ex)
414 //ForEachLoop must be put in error and the exception rethrown to notify the caller
415 DEBTRACE( "ForEachLoop::exUpdateState: " << ex.what() );
416 setState(YACS::ERROR);
421 setState(YACS::ACTIVATED); // move the calling of setState method there for adding observers for clone nodes in GUI part
424 for(i=0;i<nbOfBr;i++)
427 _execInitNodes[i]->exUpdateState();
428 _initializingCounter++;
433 _execNodes[i]->exUpdateState();
436 forwardExecStateToOriginalBody(_execNodes[nbOfBr-1]);
440 void ForEachLoop::exUpdateProgress()
442 // emit notification to all observers registered with the dispatcher on any change of the node's state
443 sendEvent("progress");
446 void ForEachLoop::getReadyTasks(std::vector<Task *>& tasks)
450 if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED);
451 if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
453 if(_nodeForSpecialCases)
455 _nodeForSpecialCases->getReadyTasks(tasks);
458 vector<Node *>::iterator iter;
459 for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
460 (*iter)->getReadyTasks(tasks);
461 for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
462 (*iter)->getReadyTasks(tasks);
463 for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
464 (*iter)->getReadyTasks(tasks);
468 int ForEachLoop::getNumberOfInputPorts() const
470 return DynParaLoop::getNumberOfInputPorts()+1;
473 void ForEachLoop::checkNoCyclePassingThrough(Node *node) throw(YACS::Exception)
478 void ForEachLoop::selectRunnableTasks(std::vector<Task *>& tasks)
482 std::list<InputPort *> ForEachLoop::getSetOfInputPort() const
484 list<InputPort *> ret=DynParaLoop::getSetOfInputPort();
485 ret.push_back((InputPort *)&_splitterNode._dataPortToDispatch);
489 std::list<InputPort *> ForEachLoop::getLocalInputPorts() const
491 list<InputPort *> ret=DynParaLoop::getLocalInputPorts();
492 ret.push_back((InputPort *)&_splitterNode._dataPortToDispatch);
496 InputPort *ForEachLoop::getInputPort(const std::string& name) const throw(YACS::Exception)
498 if(name==SplitterNode::NAME_OF_SEQUENCE_INPUT)
499 return (InputPort *)&_splitterNode._dataPortToDispatch;
501 return DynParaLoop::getInputPort(name);
504 OutputPort *ForEachLoop::getOutputPort(const std::string& name) const throw(YACS::Exception)
506 for(vector<AnySplitOutputPort *>::const_iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
508 if(name==(*iter)->getName())
509 return (OutputPort *)(*iter);
511 return DynParaLoop::getOutputPort(name);
514 OutPort *ForEachLoop::getOutPort(const std::string& name) const throw(YACS::Exception)
516 for(vector<AnySplitOutputPort *>::const_iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
518 if(name==(*iter)->getName())
519 return (OutPort *)(*iter);
521 return DynParaLoop::getOutPort(name);
524 Node *ForEachLoop::getChildByShortName(const std::string& name) const throw(YACS::Exception)
526 if(name==NAME_OF_SPLITTERNODE)
527 return (Node *)&_splitterNode;
529 return DynParaLoop::getChildByShortName(name);
532 //! Method used to notify the node that a child node has finished
534 * Update the current state and return the change state
536 * \param node : the child node that has finished
537 * \return the state change
539 YACS::Event ForEachLoop::updateStateOnFinishedEventFrom(Node *node)
541 DEBTRACE("updateStateOnFinishedEventFrom " << node->getName() << " " << node->getState());
543 switch(getIdentityOfNotifyerNode(node,id))
546 _execNodes[id]->exUpdateState();
548 _initializingCounter--;
549 if (_initializingCounter == 0) _initNode->setState(DONE);
554 storeOutValsInSeqForOutOfScopeUse(_execIds[id],id);
555 if(_execCurrentId==_splitterNode.getNumberOfElements())
556 {//No more elements of _dataPortToDispatch to treat
557 _execIds[id]=NOT_RUNNING_BRANCH_ID;
558 //analyzing if some samples are still on treatment on other branches.
559 bool isFinished=true;
560 for(int i=0;i<_execIds.size() && isFinished;i++)
561 isFinished=(_execIds[i]==NOT_RUNNING_BRANCH_ID);
566 pushAllSequenceValues();
570 _node->setState(YACS::DONE);
572 ComposedNode* compNode = dynamic_cast<ComposedNode*>(_node);
575 std::list<Node *> aChldn = compNode->getAllRecursiveConstituents();
576 std::list<Node *>::iterator iter=aChldn.begin();
577 for(;iter!=aChldn.end();iter++)
578 (*iter)->setState(YACS::DONE);
582 if (_finalizeNode == NULL)
584 // No finalize node, we just finish the loop at the end of exec nodes execution
585 setState(YACS::DONE);
590 // Run the finalize nodes, the loop will be done only when they all finish
591 _unfinishedCounter = 0; // This counter indicates how many branches are not finished
592 for (int i=0 ; i<_execIds.size() ; i++)
594 YASSERT(_execIds[i] == NOT_RUNNING_BRANCH_ID);
595 DEBTRACE("Launching finalize node for branch " << i);
596 _execFinalizeNodes[i]->exUpdateState();
597 _unfinishedCounter++;
599 return YACS::NOEVENT;
602 catch(YACS::Exception& ex)
604 DEBTRACE("ForEachLoop::updateStateOnFinishedEventFrom: "<<ex.what());
605 //no way to push results : put following nodes in FAILED state
606 //TODO could be more fine grain : put only concerned nodes in FAILED state
608 setState(YACS::ERROR);
613 else if(_state == YACS::ACTIVATED)
614 {//more elements to do and loop still activated
615 _execIds[id]=_execCurrentId;
617 _splitterNode.putSplittedValueOnRankTo(_execCurrentId++,id,false);
618 node->exUpdateState();
619 forwardExecStateToOriginalBody(node);
623 {//elements to process and loop no more activated
624 DEBTRACE("foreach loop state " << _state);
629 DEBTRACE("Finalize node finished on branch " << id);
630 _unfinishedCounter--;
633 DEBTRACE(_unfinishedCounter << " finalize nodes still running");
634 if (_unfinishedCounter == 0)
636 _finalizeNode->setState(YACS::DONE);
637 setState(YACS::DONE);
641 return YACS::NOEVENT;
647 return YACS::NOEVENT;
650 void ForEachLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
652 DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView);
653 string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
654 if(typeOfPortInstance==OutputPort::NAME)
656 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
658 for(;iter!=_outGoingPorts.end();iter++,i++)
659 if((*iter)->getRepr()==port.first)
661 if(iter!=_outGoingPorts.end())
664 (*iter)->addRepr(port.first,_intecptrsForOutGoingPorts[i]);
669 TypeCodeSeq *newTc=(TypeCodeSeq *)TypeCode::sequenceTc("","",port.first->edGetType());
670 AnySplitOutputPort *newPort=new AnySplitOutputPort(getPortName(port.first),this,newTc);
671 InterceptorInputPort *intercptor=new InterceptorInputPort(string("intercptr for ")+getPortName(port.first),this,port.first->edGetType());
672 intercptor->setRepr(newPort);
674 newPort->addRepr(port.first,intercptor);
675 _outGoingPorts.push_back(newPort);
676 _intecptrsForOutGoingPorts.push_back(intercptor);
681 throw Exception("ForEachLoop::buildDelegateOf : not implemented for DS because not specified");
684 void ForEachLoop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
686 string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
687 if(typeOfPortInstance==OutputPort::NAME)
689 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
690 for(;iter!=_outGoingPorts.end();iter++)
691 if((*iter)->getRepr()==port.first)
693 if(iter==_outGoingPorts.end())
695 string what("ForEachLoop::getDelegateOf : Port with name "); what+=port.first->getName(); what+=" not exported by ForEachLoop "; what+=_name;
696 throw Exception(what);
702 throw Exception("ForEachLoop::getDelegateOf : not implemented because not specified");
705 void ForEachLoop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
707 string typeOfPortInstance=portDwn->getNameOfTypeOfCurrentInstance();
708 if(typeOfPortInstance==OutputPort::NAME)
710 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
711 vector<InterceptorInputPort *>::iterator iter2=_intecptrsForOutGoingPorts.begin();
712 for(;iter!=_outGoingPorts.end();iter++,iter2++)
713 if((*iter)->getRepr()==portDwn)
715 //ASSERT(portUp==*iter.second)
716 if((*iter)->decrRef())
718 AnySplitOutputPort *p=*iter;
719 _outGoingPorts.erase(iter);
721 InterceptorInputPort *ip=*iter2;
722 _intecptrsForOutGoingPorts.erase(iter2);
728 OutPort *ForEachLoop::getDynOutPortByAbsName(int branchNb, const std::string& name)
730 string portName, nodeName;
731 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
732 Node *staticChild = getChildByName(nodeName);
733 return _execNodes[branchNb]->getOutPort(portName);//It's impossible(garanteed by YACS::ENGINE::ForEachLoop::buildDelegateOf)
734 //that a link starting from _initNode goes out of scope of 'this'.
737 void ForEachLoop::cleanDynGraph()
739 DynParaLoop::cleanDynGraph();
740 for(vector< SequenceAny *>::iterator iter3=_execVals.begin();iter3!=_execVals.end();iter3++)
743 for(vector< vector<AnyInputPort *> >::iterator iter4=_execOutGoingPorts.begin();iter4!=_execOutGoingPorts.end();iter4++)
744 for(vector<AnyInputPort *>::iterator iter5=(*iter4).begin();iter5!=(*iter4).end();iter5++)
746 _execOutGoingPorts.clear();
749 void ForEachLoop::storeOutValsInSeqForOutOfScopeUse(int rank, int branchNb)
751 vector<AnyInputPort *>::iterator iter;
753 for(iter=_execOutGoingPorts[branchNb].begin();iter!=_execOutGoingPorts[branchNb].end();iter++,i++)
755 Any *val=(Any *)(*iter)->getValue();
756 _execVals[i]->setEltAtRank(rank,val);
760 void ForEachLoop::prepareSequenceValues(int sizeOfSamples)
762 _execVals.resize(_outGoingPorts.size());
763 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
764 for(int i=0;iter!=_outGoingPorts.end();iter++,i++)
765 _execVals[i]=SequenceAny::New((*iter)->edGetType()->contentType(),sizeOfSamples);
768 void ForEachLoop::pushAllSequenceValues()
770 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
772 for(;iter!=_outGoingPorts.end();iter++,i++)
773 (*iter)->put((const void *)_execVals[i]);
776 void ForEachLoop::createOutputOutOfScopeInterceptors(int branchNb)
778 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
780 for(;iter!=_outGoingPorts.end();iter++,i++)
782 DEBTRACE( (*iter)->getName() << " " << (*iter)->edGetType()->kind() );
783 //AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,(*iter)->edGetType());
784 OutPort *portOut=getDynOutPortByAbsName(branchNb,getOutPortName(((*iter)->getRepr())));
785 DEBTRACE( portOut->getName() );
786 AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,portOut->edGetType());
787 portOut->addInPort(interceptor);
788 _execOutGoingPorts[branchNb].push_back(interceptor);
792 void ForEachLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
793 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
795 if(isInMyDescendance(start->getNode())==_node)
796 throw Exception("ForEachLoop::checkLinkPossibility : A link from work node to init node not permitted");
799 std::list<OutputPort *> ForEachLoop::getLocalOutputPorts() const
801 list<OutputPort *> ret;
802 ret.push_back(getOutputPort(NAME_OF_SPLITTED_SEQ_OUT));
806 void ForEachLoop::accept(Visitor *visitor)
808 visitor->visitForEachLoop(this);
811 //! Dump the node state to a stream
813 * \param os : the output stream
815 void ForEachLoop::writeDot(std::ostream &os) const
817 os << " subgraph cluster_" << getId() << " {\n" ;
818 //only one node in a loop
822 os << getId() << " -> " << _node->getId() << ";\n";
825 os << getId() << "[fillcolor=\"" ;
826 YACS::StatesForNode state=getEffectiveState();
827 os << getColorState(state);
828 os << "\" label=\"" << "Loop:" ;
829 os << getName() <<"\"];\n";
832 //! Reset the state of the node and its children depending on the parameter level
833 void ForEachLoop::resetState(int level)
836 DynParaLoop::resetState(level);
838 //Note: cleanDynGraph is not a virtual method (must be called from ForEachLoop object)
842 std::string ForEachLoop::getProgress() const
844 int nbElems = _splitterNode.getNumberOfElements();
845 std::stringstream aProgress;
847 aProgress << _currentIndex << "/" << nbElems;
850 return aProgress.str();