1 // Copyright (C) 2006-2016 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
21 #include "InputPort.hxx"
22 #include "OutputPort.hxx"
23 #include "InputDataStreamPort.hxx"
24 #include "OutputDataStreamPort.hxx"
25 #include "LinkInfo.hxx"
26 #include "Runtime.hxx"
27 #include "Visitor.hxx"
32 #include "YacsTrace.hxx"
34 using namespace YACS::ENGINE;
37 InputPort4DF2DS::InputPort4DF2DS(DFToDSForLoop *node, TypeCode* type):
38 InputPort("", node, type),
39 DataPort("", node, type),
44 void InputPort4DF2DS::getAllRepresentants(std::set<InPort *>& repr) const
46 set<InPort *> s=_node->getOutputDataStreamPort("")->edSetInPort();
47 repr.insert(s.begin(),s.end());
50 void *InputPort4DF2DS::get() const throw(YACS::Exception)
54 std::string what="InputPort4DF2DS::get : no value currently in input whith name \""; what+=_name; what+="\"";
55 throw Exception(what);
60 void InputPort4DF2DS::exRestoreInit()
70 void InputPort4DF2DS::exSaveInit()
73 _initValue->decrRef();
75 _initValue->incrRef();
78 void InputPort4DF2DS::put(const void *data) throw(ConversionException)
83 InputPort *InputPort4DF2DS::clone(Node *newHelder) const
85 throw Exception("InputPort4DF2DS::clone : internal error");
88 void InputPort4DF2DS::put(Any *data)
96 InputPort4DF2DS::~InputPort4DF2DS()
102 DFToDSForLoop::DFToDSForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
104 _name="DF2DS For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
106 _setOfInputPort.push_back(new InputPort4DF2DS(this,type));
107 _setOfOutputDataStreamPort.push_back(new OutputDataStreamPort("",this,Loop::MappingDF2DS(type)));
110 DFToDSForLoop::~DFToDSForLoop()
112 edDisconnectAllLinksWithMe();
115 void DFToDSForLoop::getReadyTasks(std::vector<Task *>& tasks)
119 InputPort *DFToDSForLoop::getInputPort(const std::string& name) const throw(YACS::Exception)
122 return Node::getInputPort(name);
124 catch(Exception& e) {}
126 list<InputPort *>::const_iterator it =_setOfInputPort.begin();
130 OutputDataStreamPort *DFToDSForLoop::getOutputDataStreamPort(const std::string& name) const throw(YACS::Exception)
132 list<OutputDataStreamPort *>::const_iterator it =_setOfOutputDataStreamPort.begin();
136 void DFToDSForLoop::load()
140 void DFToDSForLoop::execute()
145 Node *DFToDSForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
147 throw Exception("DFToDSForLoop::simpleClone : Internal error");
150 OutputPort4DS2DF::OutputPort4DS2DF(DSToDFForLoop *node, TypeCode *type):
151 OutputPort("", node, type),
152 DataPort("", node, type),
157 void OutputPort4DS2DF::getAllRepresented(std::set<OutPort *>& represented) const
159 set<OutPort *> setO=_node->getInputDataStreamPort("")->edSetOutPort();
160 for(set<OutPort *>::iterator iter=setO.begin();iter!=setO.end();iter++)
161 (*iter)->getAllRepresented(represented);
164 void OutputPort4DS2DF::put(const void *data) throw(ConversionException)
167 OutputPort::put(data);
170 OutputPort *OutputPort4DS2DF::clone(Node *newHelder) const
172 throw Exception("OutputPort4DS2DF::clone : Internal error");
175 void OutputPort4DS2DF::put(Any *data)
183 OutputPort4DS2DF::~OutputPort4DS2DF()
189 InputDataStreamPort4DS2DF::InputDataStreamPort4DS2DF(DSToDFForLoop *node, TypeCode* type):
190 InputDataStreamPort("", node, type),
191 DataPort("", node, type),
196 void InputDataStreamPort4DS2DF::getAllRepresentants(std::set<InPort *>& repr) const
198 set<InPort *> s=_node->getOutputPort("")->edSetInPort();
199 repr.insert(s.begin(),s.end());
202 DSToDFForLoop::DSToDFForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
204 _name="DS2DF For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
206 _setOfOutputPort.push_back(new OutputPort4DS2DF(this,type));
207 _setOfInputDataStreamPort.push_back(new InputDataStreamPort4DS2DF(this,type));
210 Node *DSToDFForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
212 throw Exception("DSToDFForLoop::simpleClone : Internal error");
215 DSToDFForLoop::~DSToDFForLoop()
217 edDisconnectAllLinksWithMe();
220 void DSToDFForLoop::getReadyTasks(std::vector<Task *>& tasks)
224 OutputPort *DSToDFForLoop::getOutputPort(const std::string& name) const throw(YACS::Exception)
226 list<OutputPort *>::const_iterator it = _setOfOutputPort.begin();
230 InputDataStreamPort *DSToDFForLoop::getInputDataStreamPort(const std::string& name) const throw(YACS::Exception)
232 list<InputDataStreamPort *>::const_iterator it = _setOfInputDataStreamPort.begin();
236 void DSToDFForLoop::load()
240 void DSToDFForLoop::execute()
245 FakeNodeForLoop::FakeNodeForLoop(Loop *loop, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"),
247 _normalFinish(normalFinish),
248 _internalError(internalError)
250 setState(YACS::TOACTIVATE);
251 _father=_loop->getFather();
254 FakeNodeForLoop::FakeNodeForLoop(const FakeNodeForLoop& other):ElementaryNode(other),_loop(0),
255 _normalFinish(false),_internalError(true)
259 Node *FakeNodeForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
261 return new FakeNodeForLoop(*this);
264 void FakeNodeForLoop::exForwardFailed()
266 _loop->exForwardFailed();
269 void FakeNodeForLoop::exForwardFinished()
271 _loop->exForwardFinished();
274 void FakeNodeForLoop::execute()
277 throw Exception("");//only to trigger ABORT on Executor
280 void FakeNodeForLoop::aborted()
283 _loop->setState(YACS::INTERNALERR);
285 _loop->setState(YACS::ERROR);
288 void FakeNodeForLoop::finished()
290 _loop->setState(YACS::DONE);
293 Loop::Loop(const Loop& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_nbOfTurns(0),_nodeForNullTurnOfLoops(0),_node(0)
296 _node=other._node->simpleClone(this,editionOnly);
299 Loop::Loop(const std::string& name):StaticDefinedComposedNode(name),_node(0),_nbOfTurns(0),_nodeForNullTurnOfLoops(0)
306 if(_nodeForNullTurnOfLoops)delete _nodeForNullTurnOfLoops;
307 for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
309 for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
313 void Loop::init(bool start)
315 StaticDefinedComposedNode::init(start);
318 _node->init(start); // if start is true, refresh the internal node
320 throw Exception("Loop::initLoop : no nodes specifies to be repeated ");
321 delete _nodeForNullTurnOfLoops;
322 _nodeForNullTurnOfLoops=0;
325 Node *Loop::edSetNode(Node *node)
333 string what = "Loop::edSetNode: node "; what += node->getName(); what += " is not orphan ! ";
334 throw Exception(what);
337 checkNoCrossHierachyWith(node);
338 StaticDefinedComposedNode::edRemoveChild(_node);
342 //set _modified flag so that edUpdateState() can refresh state
347 bool Loop::edAddChild(Node *node) throw(YACS::Exception)
349 return edSetNode(node);
352 Node *Loop::edRemoveNode()
354 StaticDefinedComposedNode::edRemoveChild(_node);
361 //! Collect all the child nodes that are ready
363 * \param tasks : vector of tasks to collect ready nodes
365 void Loop::getReadyTasks(std::vector<Task *>& tasks)
370 * To change the way ComposedNode state is handled, uncomment the following line
371 * see Bloc::getReadyTasks
373 if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED);
374 if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
375 if(_nodeForNullTurnOfLoops)
376 _nodeForNullTurnOfLoops->getReadyTasks(tasks);
379 _node->getReadyTasks(tasks);
380 for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
381 (*iter1)->getReadyTasks(tasks);
382 for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
383 (*iter2)->getReadyTasks(tasks);
387 void Loop::edRemoveChild(Node *node) throw(YACS::Exception)
389 StaticDefinedComposedNode::edRemoveChild(node);
395 std::list<Node *> Loop::edGetDirectDescendants() const
399 ret.push_back(_node);
403 std::list<InputPort *> Loop::getSetOfInputPort() const
405 list<InputPort *> ret=StaticDefinedComposedNode::getSetOfInputPort();
406 ret.push_back(getDecisionPort());
410 int Loop::getNumberOfInputPorts() const
412 return StaticDefinedComposedNode::getNumberOfInputPorts()+1;
415 int Loop::getMaxLevelOfParallelism() const
419 return _node->getMaxLevelOfParallelism();
422 void Loop::getWeightRegardingDPL(ComplexWeight *weight)
425 _node->getWeightRegardingDPL(weight);
428 void Loop::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
431 _node->partitionRegardingDPL(pd,zeMap);
434 Node *Loop::getChildByShortName(const std::string& name) const throw(YACS::Exception)
437 if(name==_node->getName())
439 string what("node "); what+= name ; what+=" is not a child of loop node "; what += getName();
440 throw Exception(what);
443 TypeCode* Loop::MappingDF2DS(TypeCode* type) throw(YACS::Exception)
448 TypeCode* Loop::MappingDS2DF(TypeCode* type) throw(YACS::Exception)
453 void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
455 string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
456 if(typeOfPortInstance!=InputPort::NAME ||
457 (typeOfPortInstance == InputPort::NAME &&
458 initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME &&
459 !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
461 InputPort *portCasted=(InputPort *)port;
462 set<DSToDFForLoop*>::iterator iter;
463 //Determinig if a DSToDFForLoop node has already been created for delegation of 'port'
464 for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
465 if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
467 if(iter==_inputsTraducer.end())
468 {//first time that 'port' is delegated on higher level
469 pair<set<DSToDFForLoop*>::iterator, bool> iter2=_inputsTraducer.insert(new DSToDFForLoop(this,portCasted->getName(),Loop::MappingDF2DS(portCasted->edGetType())));
471 (*iter)->getOutputPort("")->addInPort(portCasted);
474 (*iter)->loopHasOneMoreRef();
475 port=(*iter)->getInputDataStreamPort("");
478 void Loop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
480 string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
481 if(typeOfPortInstance!=OutputPort::NAME ||
482 ( typeOfPortInstance == OutputPort::NAME &&
483 finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME &&
484 !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
486 OutPort *portCasted=port.first;
487 set<DFToDSForLoop*>::iterator iter;
488 //Determinig if a DFToDSForLoop node has already been created for delegation of 'port'
489 for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
490 if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
493 if(iter==_outputsTraducer.end())
494 {//first time that 'port' is delegated on higher level
495 //_outputsTraducer.insert(new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType()));
496 kl=new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType());
497 pair<set<DFToDSForLoop*>::iterator, bool> iter2=_outputsTraducer.insert(kl);
499 portCasted->addInPort((*iter)->getInputPort(""));
504 kl->loopHasOneMoreRef();
506 edAddLink(isInMyDescendance((port.first)->getNode())->getOutGate(),kl->getInGate());
507 port.first=(*iter)->getOutputDataStreamPort("");
510 void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
512 string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
513 if(typeOfPortInstance!=InputPort::NAME ||
514 (typeOfPortInstance == InputPort::NAME &&
515 initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME &&
516 !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
518 InputPort *portCasted=(InputPort *)port;
519 set<DSToDFForLoop*>::iterator iter;
520 for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
521 if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
523 if(iter==_inputsTraducer.end())
525 string what("Loop::getDelegateOf : Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
526 throw Exception(what);
529 port=(*iter)->getInputDataStreamPort("");
532 void Loop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget,
533 const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
535 string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
536 if(typeOfPortInstance!=OutputPort::NAME ||
537 ( typeOfPortInstance == OutputPort::NAME &&
538 finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME &&
539 !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
541 OutPort *portCasted=port.first;
542 set<DFToDSForLoop*>::iterator iter;
543 for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
544 if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
546 if(iter==_outputsTraducer.end())
548 string what("Loop::getDelegateOf : Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
549 throw Exception(what);
552 port.first=(*iter)->getOutputDataStreamPort("");
555 void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
557 string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
558 if(typeOfPortInstance!=InputPort::NAME ||
559 ( typeOfPortInstance == InputPort::NAME &&
560 initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME &&
561 !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
563 InputPort *portCasted=(InputPort *)port;
564 set<DSToDFForLoop*>::iterator iter;
565 for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
566 if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
568 if(iter==_inputsTraducer.end())
570 string what("Loop::releaseDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
571 throw Exception(what);
575 port=(*iter)->getInputDataStreamPort("");
576 if((*iter)->loopHasOneLessRef())
578 (*iter)->getOutputPort("")->removeInPort(portCasted,false);
580 _inputsTraducer.erase(iter);
585 void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
589 set<DFToDSForLoop*>::iterator iter;
590 for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
591 if((*iter)->getOutputDataStreamPort("")==portUp)
593 if((*iter)->loopHasOneLessRef())
595 portDwn->removeInPort((*iter)->getInputPort(""),false);
597 _outputsTraducer.erase(iter);
601 void Loop::checkNoCyclePassingThrough(Node *node) throw(YACS::Exception)
603 //throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured");
606 void Loop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
608 Node *nodeEnd=end->getNode();
610 {//In this case 'end' port is a special port of this (for exemple ForLoop::_nbOfTimesPort)
611 //ASSERT(!direction) see Loop::checkControlDependancy (bw only)
612 solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
615 StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info);
619 * \note : States if a DF port must be considered on an upper level in hierarchy as a DS port or not from 'pointsOfView' observers.
621 * - True : a traduction DF->DS has to be done
622 * - False : no traduction needed
624 bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::list<ComposedNode *>& pointsOfView)
627 for(list<ComposedNode *>::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++)
628 ret=(*iter)->isRepeatedUnpredictablySeveralTimes();
632 //! Connect an OutPort to an InPort and add control link if necessary
634 * Connect the ports with a data link (edAddLink)
635 * In a Loop don't add control flow link : use this only to add data back links
637 * \param start : the OutPort to connect
638 * \param end : the InPort to connect
639 * \return true if a new link has been created, false otherwise.
641 bool Loop::edAddDFLink(OutPort *start, InPort *end) throw(YACS::Exception)
643 return edAddLink(start,end);
646 //! Dump the node state to a stream
648 * \param os : the output stream
650 void Loop::writeDot(std::ostream &os) const
652 os << " subgraph cluster_" << getId() << " {\n" ;
653 //only one node in a loop
657 os << getId() << " -> " << _node->getId() << ";\n";
660 os << getId() << "[fillcolor=\"" ;
661 YACS::StatesForNode state=getEffectiveState();
662 os << getColorState(state);
663 os << "\" label=\"" << "Loop:" ;
664 os << getQualifiedName() <<"\"];\n";
668 void Loop::accept(Visitor *visitor)
670 visitor->visitLoop(this);
673 void Loop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
674 std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
675 std::vector<OutPort *>& fwCross,
676 std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
677 LinkInfo& info) const
679 //First testing if end==getDecisionPort. This is the only case possible in theory.
680 if(end!=getDecisionPort())
681 return StaticDefinedComposedNode::checkControlDependancy(start,end,cross,fw,fwCross,bw,info);
683 throw Exception("Internal error occured - cross type link detected on decision port of a loop. Forbidden !");
684 fw[(ComposedNode *)this].push_back(start);
687 void Loop::checkBasicConsistency() const throw(YACS::Exception)
689 DEBTRACE("Loop::checkBasicConsistency");
690 ComposedNode::checkBasicConsistency();
692 throw Exception("For a loop, internal node is mandatory");
696 * For use only when loading a previously saved execution
699 void YACS::ENGINE::NbDoneLoader(Loop* node, int val)
701 node->_nbOfTurns = val;