]> SALOME platform Git repositories - modules/yacs.git/blob - src/engine/Bloc.cxx
Salome HOME
PR: merge from BR_DATACONV_PR tag "mergeto_trunk_25oct06"
[modules/yacs.git] / src / engine / Bloc.cxx
1 #include "Bloc.hxx"
2 #include "ElementaryNode.hxx"
3
4 using namespace YACS::ENGINE;
5 using namespace std;
6
7 Bloc::Bloc(const string& name):ComposedNode(name)
8 {
9 }
10
11 Bloc::~Bloc()
12 {
13   for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
14     delete *iter;
15 }
16
17 void Bloc::init()
18 {
19   _inGate.exReset();
20   for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
21     (*iter)->init();
22   if(_inGate.exIsReady())
23     _state=YACS::TOACTIVATE;
24   else
25     _state=YACS::INITED;
26 }
27
28 bool Bloc::isFinished()
29 {
30   return _state==YACS::DONE;
31 }
32
33 int Bloc::getNumberOfCFLinks() const
34 {
35   int ret=0;
36   for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
37     {
38       ret+=(*iter)->getOutGate()->getNbOfInGatesConnected();
39     }
40   return ret;
41 }
42
43 vector<Task *> Bloc::getNextTasks(bool& isMore)
44 {
45   vector<Task *> ret;
46   isMore=false;
47   if(_state==YACS::DONE || _state==YACS::INITED)
48     return ret;
49   for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
50     (*iter)->getReadyTasks(ret);
51   isMore=!ret.empty();
52   return ret;
53 }
54
55 void Bloc::getReadyTasks(vector<Task *>& tasks)
56 {
57   if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
58     for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
59       (*iter)->getReadyTasks(tasks);
60 }
61
62 set<ElementaryNode *> Bloc::getRecursiveConstituents()
63 {
64   set<ElementaryNode *> ret;
65   for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
66     {
67       set<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
68       ret.insert(myCurrentSet.begin(),myCurrentSet.end());
69     }
70   return ret;
71 }
72
73 /**
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.
77  */
78
79 void Bloc::exUpdateState()
80 {
81   if(_inGate.exIsReady())
82     _state=YACS::TOACTIVATE;
83 }
84
85 /**
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.
90 */
91
92 bool Bloc::edAddChild(Node *node) throw(Exception)
93 {
94   if(isNodeAlreadyAggregated(node))
95     {
96       if(node->_father==this)
97         return false;
98       else
99         throw Exception("Bloc::edAddChild : Internal error occured");
100     }
101
102   if(node->_father)
103     {
104       string what = "Bloc::edAddChild: node is not orphan: "; what += node->getName();
105       throw Exception(what);
106     }
107
108   if(isNameAlreadyUsed(node->getName()))
109     {
110       string what("Bloc::edAddChild : name "); what+=node->getName(); what+=" already exists in the scope of "; what+=_name;
111       throw Exception(what);
112     }
113
114   node->_father=this;
115   _setOfNode.insert(node);
116
117   ComposedNode *iter=node->_father;
118   while(iter)
119     {
120       for(set<InputPort *>::iterator itn = node->_setOfInputPort.begin(); itn != node->_setOfInputPort.end(); itn++)
121         iter->publishInputPort(*itn);
122       iter=iter->_father;
123     }
124
125   return true;
126 }
127
128 /**
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'.
134  */
135
136 void Bloc::edRemoveChild(Node *node) throw(Exception)
137 {
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);
145   delete node;
146 }
147
148 void Bloc::selectRunnableTasks(vector<Task *>& tasks)
149 {
150 }
151
152 bool Bloc::areAllSubNodesFinished() const
153 {
154   bool ret=true;
155   for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end() && ret;iter++)
156     if((*iter)->_state!=YACS::DONE)
157       ret=false;
158   return ret;
159 }
160
161 bool Bloc::isNodeAlreadyAggregated(Node *node) const
162 {
163   for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
164     {
165       if((*iter)==node)
166         return true;
167     }
168   return false;
169 }
170
171 bool Bloc::isNameAlreadyUsed(const string& name) const
172 {
173   for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
174       if((*iter)->getName()==name)
175         return true;
176   return false;
177 }
178
179 bool insertNodeChildrenInSet(Node *node, set<Node *> nodeSet)
180 {
181   bool verdict=true;
182   set<Node *> outNodes=node->getOutNodes();
183   for (set<Node *>::iterator iter=outNodes.begin();iter!=outNodes.end(); iter++)
184     {
185       verdict=(nodeSet.insert(*iter)).second;
186       if (verdict) verdict = insertNodeChildrenInSet((*iter),nodeSet);
187       if (!verdict) break;
188     }
189   return verdict;
190 }
191
192 /**
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'. 
195  *
196  */
197 void Bloc::checkNoCyclePassingThrough(Node *node) throw(Exception)
198 {
199   set<Node *> currentNodesToTest;
200   currentNodesToTest.insert(node);
201   if (!insertNodeChildrenInSet(node,currentNodesToTest))
202     throw Exception("Cycle has been detected");
203 }
204
205 void Bloc::initChildrenForDFS() const
206 {
207   for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
208     (*iter)->initForDFS();
209 }
210
211 /**
212  *
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)
216  *
217  */
218 YACS::Event Bloc::updateStateOnStartEventFrom(Node *node)
219 {
220   _state=YACS::ACTIVATED;
221   return YACS::START;
222 }
223
224 /**
225  *
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)
229  *
230  */
231 YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node)
232 {
233   //ASSERT(node->_father==this)
234   if(areAllSubNodesFinished())
235     {
236       _state=YACS::DONE;
237       return YACS::FINISH;//notify to father node that 'this' has becomed finished.
238     }
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.
242 }