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
21 #include "LinkInfo.hxx"
22 #include "InputPort.hxx"
23 #include "InputDataStreamPort.hxx"
24 #include "OutputPort.hxx"
25 #include "OutputDataStreamPort.hxx"
26 #include "ElementaryNode.hxx"
27 #include "Visitor.hxx"
28 #include "ForkBlocPoint.hxx"
29 #include "SetOfPoints.hxx"
30 #include "PlayGround.hxx"
37 #include "YacsTrace.hxx"
39 using namespace YACS::ENGINE;
42 /*! \class YACS::ENGINE::Bloc
43 * \brief Composed node to group elementary and composed nodes
48 Bloc::Bloc(const Bloc& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_fwLinks(0),_bwLinks(0)
50 for(list<Node *>::const_iterator iter=other._setOfNode.begin();iter!=other._setOfNode.end();iter++)
51 _setOfNode.push_back((*iter)->simpleClone(this,editionOnly));
54 vector< pair<OutGate *, InGate *> > cfLinksToReproduce=other.getSetOfInternalCFLinks();
55 vector< pair<OutGate *, InGate *> >::iterator iter1=cfLinksToReproduce.begin();
56 for(;iter1!=cfLinksToReproduce.end();iter1++)
57 edAddCFLink(getChildByName(other.getChildName((*iter1).first->getNode())),getChildByName(other.getChildName((*iter1).second->getNode())));
59 //Data + DataStream linking
60 vector< pair<OutPort *, InPort *> > linksToReproduce=other.getSetOfInternalLinks();
61 vector< pair<OutPort *, InPort *> >::iterator iter2=linksToReproduce.begin();
62 for(;iter2!=linksToReproduce.end();iter2++)
64 OutPort* pout = iter2->first;
65 InPort* pin = iter2->second;
66 if(&other == getLowestCommonAncestor(pout->getNode(), pin->getNode()))
68 edAddLink(getOutPort(other.getPortName(pout)),getInPort(other.getPortName(pin)));
73 //! Create a Bloc node with a given name
75 * \param name : the given name
77 Bloc::Bloc(const std::string& name):StaticDefinedComposedNode(name),_fwLinks(0),_bwLinks(0)
83 for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
89 //! Initialize the bloc
91 * \param start : a boolean flag indicating the kind of initialization
92 * If start is true, it's a complete initialization with reinitialization of port values
93 * If start is false, there is no initialization of port values
95 void Bloc::init(bool start)
98 for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
102 //! Indicate if the bloc execution is finished
104 * The execution bloc is finished if all its child nodes
105 * are finished with or without error or if it is disabled (not to execute)
107 bool Bloc::isFinished()
109 if(_state==YACS::DONE)return true;
110 if(_state==YACS::ERROR)return true;
111 if(_state==YACS::FAILED)return true;
112 if(_state==YACS::DISABLED)return true;
116 int Bloc::getNumberOfCFLinks() const
119 for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
120 ret+=(*iter)->getOutGate()->getNbOfInGatesConnected();
124 Node *Bloc::simpleClone(ComposedNode *father, bool editionOnly) const
126 return new Bloc(*this,father,editionOnly);
129 //! Collect all nodes that are ready to execute
131 * \param tasks : vector of tasks to collect ready nodes
133 void Bloc::getReadyTasks(std::vector<Task *>& tasks)
136 * ComposedNode state goes to ACTIVATED when one of its child has been ACTIVATED
137 * To change this uncomment the following line
138 * Then the father node will go to ACTIVATED state before its child node
140 if(_state==YACS::TOACTIVATE ) setState(YACS::ACTIVATED);
141 if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
142 for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
143 (*iter)->getReadyTasks(tasks);
146 //! Update the bloc state
148 * Update the '_state' attribute.
149 * Typically called by 'this->_inGate' when 'this->_inGate' is ready.
150 * Contrary to Node::exUpdateState no check done on inputs
151 * because internal linked DF inputports are not valid yet.
153 void Bloc::exUpdateState()
155 if(_state == YACS::DISABLED)return;
156 if(_state == YACS::DONE)return;
157 if(_inGate.exIsReady())
159 setState(YACS::ACTIVATED);
160 for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
161 if((*iter)->exIsControlReady())
162 (*iter)->exUpdateState();
166 //! Add a child node to the bloc
168 * \param node: the node to add to the bloc
169 * \return a boolean flag indicating if the node has been added
171 * If node is already a direct child of current bloc, do nothing.
172 * If node is a child of another bloc, throw exception.
173 * If node name already used in bloc, throw exception.
174 * Publish inputPorts in current bloc and ancestors.
176 bool Bloc::edAddChild(Node *node)
178 if(isNodeAlreadyAggregated(node))
180 if(node->_father==this)
184 string what = "Bloc::edAddChild : node "; what += node->getName();
185 what += " is already grand children of node";
186 throw Exception(what);
192 string what = "Bloc::edAddChild: node is not orphan: "; what += node->getName();
193 throw Exception(what);
196 checkNoCrossHierachyWith(node);
198 if(isNameAlreadyUsed(node->getName()))
200 string what("Bloc::edAddChild : name "); what+=node->getName();
201 what+=" already exists in the scope of "; what+=_name;
202 throw Exception(what);
206 _setOfNode.push_back(node);
207 //should we also set _modified flag for node ??
208 ComposedNode *iter=node->_father;
209 //set the _modified flag so that latter on edUpdateState (eventually called by isValid) refresh state
210 //better call it at end
216 * Remove 'node' from the set of direct children.
217 * @exception If 'node' is NOT the son of 'this'.
220 void Bloc::edRemoveChild(Node *node)
222 StaticDefinedComposedNode::edRemoveChild(node);
223 list<Node *>::iterator iter=find(_setOfNode.begin(),_setOfNode.end(),node);
224 if(iter!=_setOfNode.end())
226 _setOfNode.erase(iter);
231 std::vector< std::list<Node *> > Bloc::splitIntoIndependantGraph() const
233 std::size_t sz(_setOfNode.size());
234 list<Node *>::const_iterator it=_setOfNode.begin();
235 for(;it!=_setOfNode.end();it++)
236 (*it)->_colour=White;
237 it=_setOfNode.begin();
238 std::vector< list<Node *> > ret;
239 while(it!=_setOfNode.end())
241 Node *start(*it); start->_colour=Grey;
242 ret.push_back(list<Node *>());
243 list<Node *>& ll(ret.back());
244 std::queue<Node *> fifo; fifo.push(start);
247 Node *cur(fifo.front()); fifo.pop();
250 OutGate *og(cur->getOutGate());
251 list<InGate *> og2(og->edSetInGate());
252 for(list<InGate *>::const_iterator it2=og2.begin();it2!=og2.end();it2++)
254 Node *cur2((*it2)->getNode());
255 if(cur2->_colour==White)
262 InGate *ig(cur->getInGate());
263 list<OutGate *> bl(ig->getBackLinks());
264 for(list<OutGate *>::const_iterator it3=bl.begin();it3!=bl.end();it3++)
266 Node *cur3((*it3)->getNode());
267 if(cur3->_colour==White)
274 for(it=_setOfNode.begin();it!=_setOfNode.end() && (*it)->_colour!=White;it++);
279 Node *Bloc::getChildByShortName(const std::string& name) const
281 for (list<Node *>::const_iterator iter = _setOfNode.begin(); iter != _setOfNode.end(); iter++)
282 if ((*iter)->getName() == name)
284 string what("node "); what+= name ; what+=" is not a child of Bloc "; what += getName();
285 throw Exception(what);
288 bool Bloc::areAllSubNodesDone() const
290 for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
292 if((*iter)->_state == YACS::DONE)continue;
293 if((*iter)->_state == YACS::DISABLED)continue;
299 bool Bloc::areAllSubNodesFinished() const
301 for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
303 if((*iter)->_state == YACS::DONE)continue;
304 if((*iter)->_state == YACS::FAILED)continue;
305 if((*iter)->_state == YACS::DISABLED)continue;
306 if((*iter)->_state == YACS::ERROR)continue;
307 if((*iter)->_state == YACS::INTERNALERR)continue;
313 bool Bloc::isNameAlreadyUsed(const std::string& name) const
315 for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
316 if((*iter)->getName()==name)
321 bool insertNodeChildrenInSet(Node *node, std::set<Node *>& nodeSet)
324 list<Node *> outNodes=node->getOutNodes();
325 for (list<Node *>::iterator iter=outNodes.begin();iter!=outNodes.end(); iter++)
327 verdict=(nodeSet.insert(*iter)).second;
328 if (verdict) verdict = insertNodeChildrenInSet((*iter),nodeSet);
334 * \note Checks that in the forest from 'node' there are NO back-edges.
335 * \b WARNING : When using this method 'node' has to be checked in order to be part of direct children of 'this'.
338 void Bloc::checkNoCyclePassingThrough(Node *node)
340 set<Node *> currentNodesToTest;
341 //don't insert node to test in set.
342 //If it is present after insertion of connected nodes we have a loop
343 //collect all connected nodes
344 insertNodeChildrenInSet(node,currentNodesToTest);
346 if(!(currentNodesToTest.insert(node)).second)
347 throw Exception("Cycle has been detected",1);
350 std::vector< std::pair<OutGate *, InGate *> > Bloc::getSetOfInternalCFLinks() const
352 vector< pair<OutGate *, InGate *> > ret;
353 for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
355 list<InGate *> outCFLinksOfCurNode=(*iter)->_outGate.edSetInGate();
356 for(list<InGate *>::iterator iter2=outCFLinksOfCurNode.begin();iter2!=outCFLinksOfCurNode.end();iter2++)
357 ret.push_back(pair<OutGate *, InGate *>(&(*iter)->_outGate,*iter2));
364 * @note : Runtime called method. Indirectly called by StaticDefinedComposedNode::updateStateFrom which has dispatch to this method
365 * 'when event == FINISH'.
366 * WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by StaticDefinedComposedNode::notifyFrom)
368 * Calls the node's outgate OutGate::exNotifyDone if all nodes are not finished
370 YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node)
372 DEBTRACE("Bloc::updateStateOnFinishedEventFrom: " << node->getName());
373 //ASSERT(node->_father==this)
374 if(areAllSubNodesFinished())
376 setState(YACS::DONE);
377 if(!areAllSubNodesDone())
379 setState(YACS::FAILED);
382 return YACS::FINISH;//notify to father node that 'this' has becomed finished.
384 //more job to do in 'this' bloc
385 //Conversion exceptions can be thrown so catch them to control errors
388 //notify the finished node to propagate to its following nodes
389 node->exForwardFinished();
391 catch(YACS::Exception& ex)
393 //The node has failed to propagate. It must be put in error
394 DEBTRACE("Bloc::updateStateOnFinishedEventFrom: " << ex.what());
395 // notify the node it has failed
396 node->exForwardFailed();
397 setState(YACS::FAILED);
400 return YACS::NOEVENT;//no notification to father needed because from father point of view nothing happened.
403 //! Notify this bloc that a node has failed
405 * \param node : node that has emitted the event
406 * \return the event to notify to bloc's father
408 YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
410 node->exForwardFailed();
411 if(areAllSubNodesFinished())
413 setState(YACS::DONE);
414 if(!areAllSubNodesDone()){
415 setState(YACS::FAILED);
418 return YACS::FINISH;//notify to father node that 'this' has becomed finished.
420 return YACS::NOEVENT;
423 void Bloc::writeDot(std::ostream &os) const
425 os << " subgraph cluster_" << getId() << " {\n" ;
426 list<Node *>nodes=getChildren();
427 for(list<Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++)
429 (*iter)->writeDot(os);
430 string p=(*iter)->getId();
432 if((*iter)->_inGate._backLinks.size() == 0) os << getId() << " -> " << p << ";\n";
433 list<Node *>outnodes = (*iter)->getOutNodes();
434 for(list<Node *>::const_iterator itout=outnodes.begin();itout!=outnodes.end();itout++)
436 os << p << " -> " << (*itout)->getId() << ";\n";
440 os << getId() << "[fillcolor=\"" ;
441 YACS::StatesForNode state=getEffectiveState();
442 os << getColorState(state);
443 os << "\" label=\"" << "Bloc:" ;
444 os << getQualifiedName() <<"\"];\n";
447 void Bloc::accept(Visitor* visitor)
449 visitor->visitBloc(this);
453 * Returns the max level of parallelism is this. The max of parallelism is equal to the sum of the max parallelism level
454 * for all concurrent branches in \a this.
456 int Bloc::getMaxLevelOfParallelism() const
458 std::list< AbstractPoint * > pts(analyzeParallelism());
459 ForkBlocPoint fbp(pts,NULL);
460 return fbp.getMaxLevelOfParallelism();
463 std::list< AbstractPoint * > Bloc::analyzeParallelism() const
465 std::vector< std::list<Node *> > r(splitIntoIndependantGraph());
466 std::list< AbstractPoint * > pts;
467 for(std::vector< std::list<Node *> >::const_iterator it=r.begin();it!=r.end();it++)
469 SetOfPoints sop(*it);
471 pts.push_back(sop.getUniqueAndReleaseIt());
476 void Bloc::getWeightRegardingDPL(ComplexWeight *weight)
478 std::list< AbstractPoint * > pts(analyzeParallelism());
479 ForkBlocPoint fbp(pts,NULL);
480 fbp.getWeightRegardingDPL(weight);
483 void Bloc::removeRecursivelyRedundantCL()
485 StaticDefinedComposedNode::removeRecursivelyRedundantCL();
486 LinkInfo info(I_CF_USELESS);
488 performCFComputationsOnlyOneLevel(info);
489 std::set< std::pair<Node *, Node *> > linksToKill(info.getInfoUselessLinks());
490 for(std::set< std::pair<Node *, Node *> >::const_iterator it=linksToKill.begin();it!=linksToKill.end();it++)
491 edRemoveCFLink((*it).first,(*it).second);
492 destructCFComputations(info);
495 void Bloc::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
498 throw Exception("Bloc::partitionRegardingDPL : NULL pointer !");
499 std::list< AbstractPoint * > pts(analyzeParallelism());
500 ForkBlocPoint fbp(pts,NULL);
501 fbp.partitionRegardingDPL(pd,zeMap);
504 void Bloc::performCFComputationsOnlyOneLevel(LinkInfo& info) const
506 delete _fwLinks;//Normally useless
507 delete _bwLinks;//Normally useless
508 _fwLinks=new map<Node *,set<Node *> >;
509 _bwLinks=new map<Node *,set<Node *> >;
511 //a set to store all CF links : used to find fastly if two nodes are connected
512 std::set< std::pair< Node*, Node* > > links;
514 for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
517 std::list<InGate *> ingates=n1->getOutGate()->edSetInGate();
518 for(std::list<InGate *>::const_iterator it2=ingates.begin();it2!=ingates.end();it2++)
520 //CF link : n1 -> (*it2)->getNode()
521 Node* n2=(*it2)->getNode();
522 links.insert(std::pair< Node*, Node* >(n1,n2));
523 std::set<Node *> bwn1=(*_bwLinks)[n1];
524 std::set<Node *> fwn1=(*_fwLinks)[n1];
525 std::set<Node *> fwn2=(*_fwLinks)[n2];
526 std::set<Node *> bwn2=(*_bwLinks)[n2];
527 std::pair<std::set<Node*>::iterator,bool> ret;
528 for(std::set<Node *>::const_iterator iter2=bwn1.begin();iter2!=bwn1.end();iter2++)
530 for(std::set<Node *>::const_iterator it3=fwn2.begin();it3!=fwn2.end();it3++)
532 ret=(*_fwLinks)[*iter2].insert(*it3);
533 if(ret.second==false)
535 //dependency already exists (*iter2) -> (*it3) : if a direct link exists it's a useless one
536 if(links.find(std::pair< Node*, Node* >(*iter2,*it3)) != links.end())
537 info.pushUselessCFLink(*iter2,*it3);
540 ret=(*_fwLinks)[*iter2].insert(n2);
541 if(ret.second==false)
543 //dependency already exists (*iter2) -> n2 : if a direct link exists it's a useless one
544 if(links.find(std::pair< Node*, Node* >(*iter2,n2)) != links.end())
545 info.pushUselessCFLink(*iter2,n2);
548 for(std::set<Node *>::const_iterator it3=fwn2.begin();it3!=fwn2.end();it3++)
550 ret=(*_fwLinks)[n1].insert(*it3);
551 if(ret.second==false)
553 //dependency already exists n1 -> *it3 : if a direct link exists it's a useless one
554 if(links.find(std::pair< Node*, Node* >(n1,*it3)) != links.end())
555 info.pushUselessCFLink(n1,*it3);
558 ret=(*_fwLinks)[n1].insert(n2);
559 if(ret.second==false)
561 //dependency already exists n1 -> n2 : it's a useless link
562 info.pushUselessCFLink(n1,n2);
565 for(std::set<Node *>::const_iterator iter2=fwn2.begin();iter2!=fwn2.end();iter2++)
567 (*_bwLinks)[*iter2].insert(bwn1.begin(),bwn1.end());
568 (*_bwLinks)[*iter2].insert(n1);
570 (*_bwLinks)[n2].insert(bwn1.begin(),bwn1.end());
571 (*_bwLinks)[n2].insert(n1);
577 * Updates mutable structures _fwLinks and _bwLinks with the result of computation (CPU consuming method).
578 * _fwLinks is a map with a Node* as key and a set<Node*> as value. The set gives
579 * all nodes that are forwardly connected to the key node
580 * _bwLinks is a map for backward dependencies
581 * The method is : for all CF link (n1->n2)
582 * add n2 and _fwLinks[n2] in forward dependencies of n1 and _bwLinks[n1]
583 * add n1 and _bwLinks[n1] in backward dependencies of n2 and _fwLinks[n2]
585 * If a node is already in a forward dependency when adding and the direct link
586 * already exists so it's a useless link (see the code !)
588 void Bloc::performCFComputations(LinkInfo& info) const
590 StaticDefinedComposedNode::performCFComputations(info);
591 performCFComputationsOnlyOneLevel(info);
594 void Bloc::destructCFComputations(LinkInfo& info) const
596 StaticDefinedComposedNode::destructCFComputations(info);
597 delete _fwLinks; _fwLinks=0;
598 delete _bwLinks; _bwLinks=0;
602 * \b WARNING \b Needs call of performCFComputations before beeing called.
603 * Perform updates of containers regarding attributes of link 'start' -> 'end' and check the correct linking.
604 * The output is in info struct.
606 * \param start : start port
607 * \param end : end port
609 * \param fw out parameter being append if start -> end link is a forward link \b without cross type DF/DS.
610 * \param fwCross out parameter being append if start -> end link is a forward link \b with cross type DF/DS.
611 * \param bw out parameter being append if start -> end link is a backward link.
612 * \param info out parameter being informed about eventual errors.
614 void Bloc::checkControlDependancy(OutPort *start, InPort *end, bool cross,
615 std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
616 std::vector<OutPort *>& fwCross,
617 std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
618 LinkInfo& info) const
622 Node *startN=isInMyDescendance(start->getNode());
623 Node *endN=isInMyDescendance(end->getNode());
625 bw[(ComposedNode *)this].push_back(start);
626 else if(areLinked(startN,endN,true))
627 fw[(ComposedNode *)this].push_back(start);
629 if(areLinked(startN,endN,false))
630 bw[(ComposedNode *)this].push_back(start);
632 info.pushErrLink(start,end,E_UNPREDICTABLE_FED);
635 if(arePossiblyRunnableAtSameTime(isInMyDescendance(start->getNode()),isInMyDescendance(end->getNode())))
636 fwCross.push_back(start);
638 info.pushErrLink(start,end,E_DS_LINK_UNESTABLISHABLE);
641 //! Check if two nodes are linked
643 * 'start' and 'end' \b must be direct son of 'this'.
644 * Typically used for data link.
645 * \param start : start node
646 * \param end : end node
647 * \param fw indicates if it is a forward link searched (true : default value) or a backward link serach.
648 * \return if true or false
650 bool Bloc::areLinked(Node *start, Node *end, bool fw) const
652 set<Node *>& nexts=fw ? (*_fwLinks)[start] : (*_bwLinks)[start];
653 return nexts.find(end)!=nexts.end();
656 //! Check if two nodes can run in parallel
658 * Typically used for stream link.
659 * 'start' and 'end' \b must be direct son of 'this'.
660 * \param start : start node
661 * \param end : end node
662 * \return true or false
664 bool Bloc::arePossiblyRunnableAtSameTime(Node *start, Node *end) const
666 set<Node *>& nexts=(*_fwLinks)[start];
667 set<Node *>& preds=(*_bwLinks)[start];
668 return nexts.find(end)==nexts.end() && preds.find(end)==preds.end();
671 //! Check control flow links
673 * \param starts If different of 0, must aggregate at leat \b 1 element.
674 * \param end : end port
675 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
676 * \param direction If true : forward direction else backward direction.
677 * \param info : collected information
679 void Bloc::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
681 if(alreadyFed==FREE_ST || alreadyFed==FED_ST)
683 map<Node *,list <OutPort *> > classPerNodes;
684 for(list< OutPort *>::const_iterator iter1=starts.begin();iter1!=starts.end();iter1++)
685 classPerNodes[isInMyDescendance((*iter1)->getNode())].push_back(*iter1);
686 set<Node *> allNodes;
687 for(map<Node *,list <OutPort *> >::iterator iter2=classPerNodes.begin();iter2!=classPerNodes.end();iter2++)
688 allNodes.insert((*iter2).first);
689 vector<Node *> okAndUseless1,useless2;
690 seekOkAndUseless1(okAndUseless1,allNodes);
691 seekUseless2(useless2,allNodes);//after this point allNodes contains collapses
692 verdictForOkAndUseless1(classPerNodes,end,okAndUseless1,alreadyFed,direction,info);
693 verdictForCollapses(classPerNodes,end,allNodes,alreadyFed,direction,info);
694 verdictForOkAndUseless1(classPerNodes,end,useless2,alreadyFed,direction,info);
696 else if(alreadyFed==FED_DS_ST)
697 for(list< OutPort *>::const_iterator iter1=starts.begin();iter1!=starts.end();iter1++)
698 info.pushErrLink(*iter1,end,E_COLLAPSE_DFDS);
701 void Bloc::initComputation() const
703 for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
705 (*iter)->_colour=White;
706 (*iter)->getInGate()->exReset();
707 (*iter)->getOutGate()->exReset();
712 * Part of final step for CF graph anylizing. This is the part of non collapse nodes.
715 * \param candidates :
716 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
718 * \param info : collected information
720 void Bloc::verdictForOkAndUseless1(const std::map<Node *,std::list <OutPort *> >& pool, InputPort *end,
721 const std::vector<Node *>& candidates, unsigned char& alreadyFed,
722 bool direction, LinkInfo& info)
724 for(vector<Node *>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
726 const list<OutPort *>& mySet=(*pool.find(*iter)).second;
729 if(alreadyFed==FREE_ST)
731 alreadyFed=FED_ST;//This the final choice. General case !
733 info.pushInfoLink(*(mySet.begin()),end,I_BACK);
735 else if(alreadyFed==FED_ST)
736 info.pushInfoLink(*(mySet.begin()),end,direction ? I_USELESS : I_BACK_USELESS);//Second or more turn in case of alreadyFed==FREE_ST before call of this method
740 if(dynamic_cast<ElementaryNode *>(*iter))
743 if(alreadyFed==FREE_ST)
744 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
745 else if(alreadyFed==FED_ST)
746 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
747 for(list<OutPort *>::const_iterator iter2=mySet.begin();iter2!=mySet.end();iter2++)
748 info.pushWarnLink(*iter2,end,reason);
751 ((ComposedNode *)(*iter))->checkCFLinks(mySet,end,alreadyFed,direction,info);//Thanks to recursive model!
757 * Part of final step for CF graph anylizing. This is the part of collapses nodes.
760 * \param candidates :
761 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
763 * \param info : collected information
765 void Bloc::verdictForCollapses(const std::map<Node *,std::list <OutPort *> >& pool, InputPort *end,
766 const std::set<Node *>& candidates, unsigned char& alreadyFed,
767 bool direction, LinkInfo& info)
769 info.startCollapseTransac();
770 for(set<Node *>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
772 const list<OutPort *>& mySet=(*pool.find(*iter)).second;
775 if(alreadyFed==FREE_ST)
776 info.pushWarnLink(*(mySet.begin()),end,direction ? W_COLLAPSE : W_BACK_COLLAPSE);
777 else if(alreadyFed==FED_ST)
778 info.pushWarnLink(*(mySet.begin()),end,direction ? W_COLLAPSE_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS);
782 if(dynamic_cast<ElementaryNode *>(*iter))
785 if(alreadyFed==FREE_ST)
786 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
787 else if(alreadyFed==FED_ST)
788 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
789 for(list<OutPort *>::const_iterator iter2=mySet.begin();iter2!=mySet.end();iter2++)
790 info.pushWarnLink(*iter2,end,reason);
794 ((ComposedNode *)(*iter))->checkCFLinks(mySet,end,alreadyFed,direction,info);//Thanks to recursive model!
796 if(alreadyFed==FREE_ST)
797 reason=direction ? W_COLLAPSE : W_BACK_COLLAPSE;
798 else if(alreadyFed==FED_ST)
799 reason=direction ? W_COLLAPSE_AND_USELESS : W_BACK_COLLAPSE_AND_USELESS;
800 for(list<OutPort *>::const_iterator iter2=mySet.begin();iter2!=mySet.end();iter2++)
801 info.pushWarnLink(*iter2,end,reason);
805 if(!candidates.empty())
806 if(alreadyFed==FREE_ST)
808 info.endCollapseTransac();
812 * \b WARNING use this method only after having called Bloc::performCFComputations method.
813 * \param okAndUseless1 out param contains at the end, the nodes without any collapse.
814 * \param allNodes in/out param. At the end, all the nodes in 'okAndUseless1' are deleted from 'allNodes'.
816 void Bloc::seekOkAndUseless1(std::vector<Node *>& okAndUseless1, std::set<Node *>& allNodes) const
818 set<Node *>::iterator iter=allNodes.begin();
819 while(iter!=allNodes.end())
821 set<Node *>& whereToFind=(*_bwLinks)[*iter];
822 std::set<Node *>::iterator iter2;
823 for(iter2=allNodes.begin();iter2!=allNodes.end();iter2++)
824 if((*iter)!=(*iter2))
825 if(whereToFind.find(*iter2)==whereToFind.end())
827 if(iter2!=allNodes.end())
831 okAndUseless1.push_back((*iter));
832 allNodes.erase(iter);
833 iter=allNodes.begin();
839 * \b WARNING use this method only after having called Bloc::performCFComputations method.
840 * For params see Bloc::seekOkAndUseless1.
842 void Bloc::seekUseless2(std::vector<Node *>& useless2, std::set<Node *>& allNodes) const
844 set<Node *>::iterator iter=allNodes.begin();
845 while(iter!=allNodes.end())
847 set<Node *>& whereToFind=(*_fwLinks)[*iter];
848 std::set<Node *>::iterator iter2;
849 for(iter2=allNodes.begin();iter2!=allNodes.end();iter2++)
850 if((*iter)!=(*iter2))
851 if(whereToFind.find(*iter2)==whereToFind.end())
853 if(iter2!=allNodes.end())
859 useless2.push_back((*iter));
860 allNodes.erase(iter);
861 iter=allNodes.begin();
867 * Internal method : Given a succeful path : updates 'fastFinder'
869 void Bloc::updateWithNewFind(const std::vector<Node *>& path, std::map<Node *, std::set<Node *> >& fastFinder)
873 vector<Node *>::const_iterator iter=path.begin(); iter++;
874 vector<Node *>::const_iterator iter2=path.end(); iter2-=1;
875 for(;iter!=iter2;iter++)
876 fastFinder[*iter].insert(*(iter+1));
881 * Internal method : After all paths have been found, useless CF links are searched
883 void Bloc::findUselessLinksIn(const std::list< std::vector<Node *> >& res , LinkInfo& info)
886 list< vector<Node *> >::const_iterator whereToPeerAt;
887 for(list< vector<Node *> >::const_iterator iter=res.begin();iter!=res.end();iter++)
888 if((*iter).size()>maxSize)
890 maxSize=(*iter).size();
896 vector<Node *>::const_iterator iter2=(*whereToPeerAt).begin();
897 map<Node *,bool>::iterator iter4;
898 set<Node *> searcher(iter2+1,(*whereToPeerAt).end());//to boost research
899 for(;iter2!=((*whereToPeerAt).end()-2);iter2++)
901 list< pair<InGate *,bool> >& nexts=(*iter2)->getOutGate()->edMapInGate();
902 for(list< pair<InGate *,bool> >::iterator iter4=nexts.begin();iter4!=nexts.end();iter4++)
903 if((*iter4).first->getNode()!=*(iter2+1))
904 if(searcher.find((*iter4).first->getNode())!=searcher.end())
905 info.pushUselessCFLink(*iter2,(*iter4).first->getNode());
906 searcher.erase(*iter2);