1 // Copyright (C) 2006-2013 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.
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)
300 ForEachLoop::ForEachLoop(const ForEachLoop& other, ComposedNode *father, bool editionOnly):DynParaLoop(other,father,editionOnly),
301 _splitterNode(other._splitterNode,this),
302 _execCurrentId(0),_nodeForSpecialCases(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);
339 void ForEachLoop::exUpdateState()
341 DEBTRACE("ForEachLoop::exUpdateState");
342 if(_state == YACS::DISABLED)
344 if(_inGate.exIsReady())
346 //internal graph update
348 int nbOfBr=_nbOfBranches.getIntValue();
349 int nbOfElts=_splitterNode.getNumberOfElements();
351 DEBTRACE("nbOfElts=" << nbOfElts);
352 DEBTRACE("nbOfBr=" << nbOfBr);
356 prepareSequenceValues(0);
357 delete _nodeForSpecialCases;
358 _nodeForSpecialCases=new FakeNodeForForEachLoop(this,true);
359 setState(YACS::ACTIVATED);
364 delete _nodeForSpecialCases;
365 _nodeForSpecialCases=new FakeNodeForForEachLoop(this,getAllOutPortsLeavingCurrentScope().empty());
366 setState(YACS::ACTIVATED);
371 _execNodes.resize(nbOfBr);
372 _execIds.resize(nbOfBr);
373 _execOutGoingPorts.resize(nbOfBr);
374 prepareSequenceValues(nbOfElts);
376 _execInitNodes.resize(nbOfBr);
377 _initializingCounter = 0;
379 _execFinalizeNodes.resize(nbOfBr);
381 vector<Node *> origNodes;
382 origNodes.push_back(_initNode);
383 origNodes.push_back(_node);
384 origNodes.push_back(_finalizeNode);
386 //Conversion exceptions can be thrown by createOutputOutOfScopeInterceptors
387 //so catch them to control errors
390 for(i=0;i<nbOfBr;i++)
392 DEBTRACE( "-------------- 1 " << i << " " << _execCurrentId);
393 _execIds[i]=_execCurrentId;
394 DEBTRACE( "-------------- 2" );
395 vector<Node *> clonedNodes = cloneAndPlaceNodesCoherently(origNodes);
397 _execInitNodes[i] = clonedNodes[0];
398 _execNodes[i] = clonedNodes[1];
400 _execFinalizeNodes[i] = clonedNodes[2];
401 DEBTRACE( "-------------- 4" );
402 prepareInputsFromOutOfScope(i);
403 DEBTRACE( "-------------- 5" );
404 createOutputOutOfScopeInterceptors(i);
405 DEBTRACE( "-------------- 6" );
406 _splitterNode.putSplittedValueOnRankTo(_execCurrentId++,i,true);
407 DEBTRACE( "-------------- 7" );
410 catch(YACS::Exception& ex)
412 //ForEachLoop must be put in error and the exception rethrown to notify the caller
413 DEBTRACE( "ForEachLoop::exUpdateState: " << ex.what() );
414 setState(YACS::ERROR);
419 setState(YACS::ACTIVATED); // move the calling of setState method there for adding observers for clone nodes in GUI part
422 for(i=0;i<nbOfBr;i++)
425 _execInitNodes[i]->exUpdateState();
426 _initializingCounter++;
431 _execNodes[i]->exUpdateState();
434 forwardExecStateToOriginalBody(_execNodes[nbOfBr-1]);
438 void ForEachLoop::getReadyTasks(std::vector<Task *>& tasks)
442 if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED);
443 if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
445 if(_nodeForSpecialCases)
447 _nodeForSpecialCases->getReadyTasks(tasks);
450 vector<Node *>::iterator iter;
451 for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
452 (*iter)->getReadyTasks(tasks);
453 for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
454 (*iter)->getReadyTasks(tasks);
455 for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
456 (*iter)->getReadyTasks(tasks);
460 int ForEachLoop::getNumberOfInputPorts() const
462 return DynParaLoop::getNumberOfInputPorts()+1;
465 void ForEachLoop::checkNoCyclePassingThrough(Node *node) throw(YACS::Exception)
470 void ForEachLoop::selectRunnableTasks(std::vector<Task *>& tasks)
474 std::list<InputPort *> ForEachLoop::getSetOfInputPort() const
476 list<InputPort *> ret=DynParaLoop::getSetOfInputPort();
477 ret.push_back((InputPort *)&_splitterNode._dataPortToDispatch);
481 std::list<InputPort *> ForEachLoop::getLocalInputPorts() const
483 list<InputPort *> ret=DynParaLoop::getLocalInputPorts();
484 ret.push_back((InputPort *)&_splitterNode._dataPortToDispatch);
488 InputPort *ForEachLoop::getInputPort(const std::string& name) const throw(YACS::Exception)
490 if(name==SplitterNode::NAME_OF_SEQUENCE_INPUT)
491 return (InputPort *)&_splitterNode._dataPortToDispatch;
493 return DynParaLoop::getInputPort(name);
496 OutputPort *ForEachLoop::getOutputPort(const std::string& name) const throw(YACS::Exception)
498 for(vector<AnySplitOutputPort *>::const_iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
500 if(name==(*iter)->getName())
501 return (OutputPort *)(*iter);
503 return DynParaLoop::getOutputPort(name);
506 OutPort *ForEachLoop::getOutPort(const std::string& name) const throw(YACS::Exception)
508 for(vector<AnySplitOutputPort *>::const_iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
510 if(name==(*iter)->getName())
511 return (OutPort *)(*iter);
513 return DynParaLoop::getOutPort(name);
516 Node *ForEachLoop::getChildByShortName(const std::string& name) const throw(YACS::Exception)
518 if(name==NAME_OF_SPLITTERNODE)
519 return (Node *)&_splitterNode;
521 return DynParaLoop::getChildByShortName(name);
524 //! Method used to notify the node that a child node has finished
526 * Update the current state and return the change state
528 * \param node : the child node that has finished
529 * \return the state change
531 YACS::Event ForEachLoop::updateStateOnFinishedEventFrom(Node *node)
533 DEBTRACE("updateStateOnFinishedEventFrom " << node->getName() << " " << node->getState());
535 switch(getIdentityOfNotifyerNode(node,id))
538 _execNodes[id]->exUpdateState();
540 _initializingCounter--;
541 if (_initializingCounter == 0) _initNode->setState(DONE);
544 storeOutValsInSeqForOutOfScopeUse(_execIds[id],id);
545 if(_execCurrentId==_splitterNode.getNumberOfElements())
546 {//No more elements of _dataPortToDispatch to treat
547 _execIds[id]=NOT_RUNNING_BRANCH_ID;
548 //analyzing if some samples are still on treatment on other branches.
549 bool isFinished=true;
550 for(int i=0;i<_execIds.size() && isFinished;i++)
551 isFinished=(_execIds[i]==NOT_RUNNING_BRANCH_ID);
556 pushAllSequenceValues();
560 _node->setState(YACS::DONE);
562 ComposedNode* compNode = dynamic_cast<ComposedNode*>(_node);
565 std::list<Node *> aChldn = compNode->getAllRecursiveConstituents();
566 std::list<Node *>::iterator iter=aChldn.begin();
567 for(;iter!=aChldn.end();iter++)
568 (*iter)->setState(YACS::DONE);
572 if (_finalizeNode == NULL)
574 // No finalize node, we just finish the loop at the end of exec nodes execution
575 setState(YACS::DONE);
580 // Run the finalize nodes, the loop will be done only when they all finish
581 _unfinishedCounter = 0; // This counter indicates how many branches are not finished
582 for (int i=0 ; i<_execIds.size() ; i++)
584 YASSERT(_execIds[i] == NOT_RUNNING_BRANCH_ID);
585 DEBTRACE("Launching finalize node for branch " << i);
586 _execFinalizeNodes[i]->exUpdateState();
587 _unfinishedCounter++;
589 return YACS::NOEVENT;
592 catch(YACS::Exception& ex)
594 DEBTRACE("ForEachLoop::updateStateOnFinishedEventFrom: "<<ex.what());
595 //no way to push results : put following nodes in FAILED state
596 //TODO could be more fine grain : put only concerned nodes in FAILED state
598 setState(YACS::ERROR);
603 else if(_state == YACS::ACTIVATED)
604 {//more elements to do and loop still activated
605 _execIds[id]=_execCurrentId;
607 _splitterNode.putSplittedValueOnRankTo(_execCurrentId++,id,false);
608 node->exUpdateState();
609 forwardExecStateToOriginalBody(node);
613 {//elements to process and loop no more activated
614 DEBTRACE("foreach loop state " << _state);
619 DEBTRACE("Finalize node finished on branch " << id);
620 _unfinishedCounter--;
621 DEBTRACE(_unfinishedCounter << " finalize nodes still running");
622 if (_unfinishedCounter == 0)
624 _finalizeNode->setState(YACS::DONE);
625 setState(YACS::DONE);
629 return YACS::NOEVENT;
635 return YACS::NOEVENT;
638 void ForEachLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
640 DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView);
641 string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
642 if(typeOfPortInstance==OutputPort::NAME)
644 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
646 for(;iter!=_outGoingPorts.end();iter++,i++)
647 if((*iter)->getRepr()==port.first)
649 if(iter!=_outGoingPorts.end())
652 (*iter)->addRepr(port.first,_intecptrsForOutGoingPorts[i]);
657 TypeCodeSeq *newTc=(TypeCodeSeq *)TypeCode::sequenceTc("","",port.first->edGetType());
658 AnySplitOutputPort *newPort=new AnySplitOutputPort(getPortName(port.first),this,newTc);
659 InterceptorInputPort *intercptor=new InterceptorInputPort(string("intercptr for ")+getPortName(port.first),this,port.first->edGetType());
660 intercptor->setRepr(newPort);
662 newPort->addRepr(port.first,intercptor);
663 _outGoingPorts.push_back(newPort);
664 _intecptrsForOutGoingPorts.push_back(intercptor);
669 throw Exception("ForEachLoop::buildDelegateOf : not implemented for DS because not specified");
672 void ForEachLoop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
674 string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
675 if(typeOfPortInstance==OutputPort::NAME)
677 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
678 for(;iter!=_outGoingPorts.end();iter++)
679 if((*iter)->getRepr()==port.first)
681 if(iter==_outGoingPorts.end())
683 string what("ForEachLoop::getDelegateOf : Port with name "); what+=port.first->getName(); what+=" not exported by ForEachLoop "; what+=_name;
684 throw Exception(what);
690 throw Exception("ForEachLoop::getDelegateOf : not implemented because not specified");
693 void ForEachLoop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
695 string typeOfPortInstance=portDwn->getNameOfTypeOfCurrentInstance();
696 if(typeOfPortInstance==OutputPort::NAME)
698 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
699 vector<InterceptorInputPort *>::iterator iter2=_intecptrsForOutGoingPorts.begin();
700 for(;iter!=_outGoingPorts.end();iter++,iter2++)
701 if((*iter)->getRepr()==portDwn)
703 //ASSERT(portUp==*iter.second)
704 if((*iter)->decrRef())
706 AnySplitOutputPort *p=*iter;
707 _outGoingPorts.erase(iter);
709 InterceptorInputPort *ip=*iter2;
710 _intecptrsForOutGoingPorts.erase(iter2);
716 OutPort *ForEachLoop::getDynOutPortByAbsName(int branchNb, const std::string& name)
718 string portName, nodeName;
719 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
720 Node *staticChild = getChildByName(nodeName);
721 return _execNodes[branchNb]->getOutPort(portName);//It's impossible(garanteed by YACS::ENGINE::ForEachLoop::buildDelegateOf)
722 //that a link starting from _initNode goes out of scope of 'this'.
725 void ForEachLoop::cleanDynGraph()
727 DynParaLoop::cleanDynGraph();
728 for(vector< SequenceAny *>::iterator iter3=_execVals.begin();iter3!=_execVals.end();iter3++)
731 for(vector< vector<AnyInputPort *> >::iterator iter4=_execOutGoingPorts.begin();iter4!=_execOutGoingPorts.end();iter4++)
732 for(vector<AnyInputPort *>::iterator iter5=(*iter4).begin();iter5!=(*iter4).end();iter5++)
734 _execOutGoingPorts.clear();
737 void ForEachLoop::storeOutValsInSeqForOutOfScopeUse(int rank, int branchNb)
739 vector<AnyInputPort *>::iterator iter;
741 for(iter=_execOutGoingPorts[branchNb].begin();iter!=_execOutGoingPorts[branchNb].end();iter++,i++)
743 Any *val=(Any *)(*iter)->getValue();
744 _execVals[i]->setEltAtRank(rank,val);
748 void ForEachLoop::prepareSequenceValues(int sizeOfSamples)
750 _execVals.resize(_outGoingPorts.size());
751 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
752 for(int i=0;iter!=_outGoingPorts.end();iter++,i++)
753 _execVals[i]=SequenceAny::New((*iter)->edGetType()->contentType(),sizeOfSamples);
756 void ForEachLoop::pushAllSequenceValues()
758 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
760 for(;iter!=_outGoingPorts.end();iter++,i++)
761 (*iter)->put((const void *)_execVals[i]);
764 void ForEachLoop::createOutputOutOfScopeInterceptors(int branchNb)
766 vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
768 for(;iter!=_outGoingPorts.end();iter++,i++)
770 DEBTRACE( (*iter)->getName() << " " << (*iter)->edGetType()->kind() );
771 //AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,(*iter)->edGetType());
772 OutPort *portOut=getDynOutPortByAbsName(branchNb,getOutPortName(((*iter)->getRepr())));
773 DEBTRACE( portOut->getName() );
774 AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,portOut->edGetType());
775 portOut->addInPort(interceptor);
776 _execOutGoingPorts[branchNb].push_back(interceptor);
780 void ForEachLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
781 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
783 if(isInMyDescendance(start->getNode())==_node)
784 throw Exception("ForEachLoop::checkLinkPossibility : A link from work node to init node not permitted");
787 std::list<OutputPort *> ForEachLoop::getLocalOutputPorts() const
789 list<OutputPort *> ret;
790 ret.push_back(getOutputPort(NAME_OF_SPLITTED_SEQ_OUT));
794 void ForEachLoop::accept(Visitor *visitor)
796 visitor->visitForEachLoop(this);
799 //! Dump the node state to a stream
801 * \param os : the output stream
803 void ForEachLoop::writeDot(std::ostream &os) const
805 os << " subgraph cluster_" << getId() << " {\n" ;
806 //only one node in a loop
810 os << getId() << " -> " << _node->getId() << ";\n";
813 os << getId() << "[fillcolor=\"" ;
814 YACS::StatesForNode state=getEffectiveState();
815 os << getColorState(state);
816 os << "\" label=\"" << "Loop:" ;
817 os << getName() <<"\"];\n";
820 //! Reset the state of the node and its children depending on the parameter level
821 void ForEachLoop::resetState(int level)
824 DynParaLoop::resetState(level);
826 //Note: cleanDynGraph is not a virtual method (must be called from ForEachLoop object)