2 #include "ElementaryNode.hxx"
4 using namespace YACS::ENGINE;
7 Bloc::Bloc(const string& name):ComposedNode(name)
13 for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
20 for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
22 if(_inGate.exIsReady())
23 _state=YACS::TOACTIVATE;
28 bool Bloc::isFinished()
30 return _state==YACS::DONE;
33 int Bloc::getNumberOfCFLinks() const
36 for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
38 ret+=(*iter)->getOutGate()->getNbOfInGatesConnected();
43 vector<Task *> Bloc::getNextTasks(bool& isMore)
47 if(_state==YACS::DONE || _state==YACS::INITED)
49 for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
50 (*iter)->getReadyTasks(ret);
55 void Bloc::getReadyTasks(vector<Task *>& tasks)
57 if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
58 for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
59 (*iter)->getReadyTasks(tasks);
62 set<ElementaryNode *> Bloc::getRecursiveConstituents()
64 set<ElementaryNode *> ret;
65 for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
67 set<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
68 ret.insert(myCurrentSet.begin(),myCurrentSet.end());
74 * Update the '_state' attribute.
75 * Typically called by 'this->_inGate' when 'this->_inGate' is ready. Contrary to Node::exUpdateState no check done on inputs
76 * because internal linked DF inputports are not valid yet.
79 void Bloc::exUpdateState()
81 if(_inGate.exIsReady())
82 _state=YACS::TOACTIVATE;
86 * If node is already a direct child of current bloc, do nothing.
87 * If node is a child of another bloc, throw exception.
88 * If node name already used in bloc, throw exception.
89 * Publish inputPorts in current bloc and ancestors.
92 bool Bloc::edAddChild(Node *node) throw(Exception)
94 if(isNodeAlreadyAggregated(node))
96 if(node->_father==this)
99 throw Exception("Bloc::edAddChild : Internal error occured");
104 string what = "Bloc::edAddChild: node is not orphan: "; what += node->getName();
105 throw Exception(what);
108 if(isNameAlreadyUsed(node->getName()))
110 string what("Bloc::edAddChild : name "); what+=node->getName(); what+=" already exists in the scope of "; what+=_name;
111 throw Exception(what);
115 _setOfNode.insert(node);
117 ComposedNode *iter=node->_father;
120 for(set<InputPort *>::iterator itn = node->_setOfInputPort.begin(); itn != node->_setOfInputPort.end(); itn++)
121 iter->publishInputPort(*itn);
129 * Remove 'node' from the set of direct children.
130 * WARNING 1 : node is destroyed after invocation of this method because Bloc class has ownership of its child nodes.
131 * WARNING 2 : all links to 'node' are automatically desactivated. As consequence this method is quite heavy for big graphs due to
132 * unilateral storing policy of links.
133 * @exception If 'node' is NOT the direct son of 'this'.
136 void Bloc::edRemoveChild(Node *node) throw(Exception)
138 if(node->_father!=this)
139 throw Exception("Bloc::edRemoveChild : node is NOT managed by this");
140 if(!isNodeAlreadyAggregated(node))
141 throw Exception("Bloc::edRemoveChild : Internal error occured");
142 ComposedNode *myRootNode=getRootNode();
143 myRootNode->disconnectAllLinksConnectedTo(node);
144 _setOfNode.erase(node);
148 void Bloc::selectRunnableTasks(vector<Task *>& tasks)
152 bool Bloc::areAllSubNodesFinished() const
155 for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end() && ret;iter++)
156 if((*iter)->_state!=YACS::DONE)
161 bool Bloc::isNodeAlreadyAggregated(Node *node) const
163 for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
171 bool Bloc::isNameAlreadyUsed(const string& name) const
173 for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
174 if((*iter)->getName()==name)
179 bool insertNodeChildrenInSet(Node *node, set<Node *> nodeSet)
182 set<Node *> outNodes=node->getOutNodes();
183 for (set<Node *>::iterator iter=outNodes.begin();iter!=outNodes.end(); iter++)
185 verdict=(nodeSet.insert(*iter)).second;
186 if (verdict) verdict = insertNodeChildrenInSet((*iter),nodeSet);
193 * @note : Checks that in the forest from 'node' there are NO back-edges.
194 * WARNING : When using this method 'node' has to be checked in order to be part of direct children of 'this'.
197 void Bloc::checkNoCyclePassingThrough(Node *node) throw(Exception)
199 set<Node *> currentNodesToTest;
200 currentNodesToTest.insert(node);
201 if (!insertNodeChildrenInSet(node,currentNodesToTest))
202 throw Exception("Cycle has been detected");
205 void Bloc::initChildrenForDFS() const
207 for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
208 (*iter)->initForDFS();
213 * @note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
214 * 'when event == START'.
215 * WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by ComposedNode::notifyFrom)
218 YACS::Event Bloc::updateStateOnStartEventFrom(Node *node)
220 _state=YACS::ACTIVATED;
226 * @note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
227 * 'when event == FINISH'.
228 * WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by ComposedNode::notifyFrom)
231 YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node)
233 //ASSERT(node->_father==this)
234 if(areAllSubNodesFinished())
237 return YACS::FINISH;//notify to father node that 'this' has becomed finished.
239 //more job to do in 'this'
240 node->_outGate.exNotifyDone();
241 return YACS::NOEVENT;//no notification to father needed because from father point of view nothing happened.