]> SALOME platform Git repositories - modules/yacs.git/blob - src/engine/ComposedNode.cxx
Salome HOME
PR: first version from Antony GEAY, with directory restructuration
[modules/yacs.git] / src / engine / ComposedNode.cxx
1 #include "ComposedNode.hxx"
2 #include "InputPort.hxx"
3 #include "OutputPort.hxx"
4 #include "ElementaryNode.hxx"
5
6 #include <set>
7
8 using namespace YACS::ENGINE;
9
10 ComposedNode::ComposedNode(const std::string& name):Node(name)
11 {
12 }
13
14 /**
15  *
16  * @ note : Runtime called method. Overloads the Scheduler::notifyFrom abstract method. Typically Called in Executor (in a parallel thread or not) by the Task 'task'
17  *          to inform the scheduler that an event coded 'event' (in Executor static const var) happened. Contrary to updateStateFrom several level may exist between 'sender' and 'this'.
18  *
19  */
20 void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
21                               YACS::Event event   //* I : event emitted
22                               )
23 {
24   ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
25   //ASSERT(taskTyped != 0)
26   YACS::Event curEvent=event;
27   Node *lminus1LevelNode=taskTyped;
28   ComposedNode *curLevelNode=taskTyped->_father;
29   curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
30   while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
31     {
32       lminus1LevelNode=curLevelNode;
33       curLevelNode=curLevelNode->_father;
34       curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
35     }
36 }
37
38 /**
39  * @ note : Add a dataflow link.
40  *          Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
41  * @ exception : incompatibility between input and output (type), or 'start'/'end' is/are NOT in/outputPort
42  *               contained in a node in descendance of 'this', or a mutilple link to an input not supporting it.
43  * @ return : true if a new link has been created, false otherwise.
44  */
45 bool ComposedNode::edAddLink(OutputPort *start, InputPort *end) throw(Exception)
46 {
47   ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
48   std::list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
49   std::list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
50   checkInMyDescendance(lwstCmnAnctr);
51   ComposedNode *iterS=start->getNode()->_father;
52   OutPort *currentPortO=start;
53   while(iterS!=lwstCmnAnctr)
54     {
55       currentPortO=iterS->buildDelegateOf(currentPortO, allAscendanceOfNodeEnd);
56       iterS=iterS->_father;
57     }
58   iterS=end->getNode()->_father;
59   InPort *currentPortI=end;
60   while(iterS!=lwstCmnAnctr)
61     {
62       currentPortI=iterS->buildDelegateOf(currentPortI, allAscendanceOfNodeEnd);
63       iterS=iterS->_father;
64     }
65   return currentPortO->addInPort(currentPortI);
66 }
67
68 /**
69  * @ note : Add a controlflow link.
70  *          Precondition : 'start' AND 'end' are in/outGate contained in a node in DIRECT descendance of 'this'.
71  * @ exception : If a cycle has been detected, or incompatibility between input and output, or 'start'/'end' is/are NOT in/outputPort
72  *               contained in a node in descendance of 'this', or a mutilple link to an input not supporting it.
73  * @ return : true if a new link has been created, false otherwise. 
74  */
75 bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(Exception)
76 {
77   ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
78   if(father!=this)
79     {
80       checkInMyDescendance(father);
81       return father->edAddLink(start,end);
82     }
83   bool ret=start->edAddInGate(end);
84   if(ret)
85     checkNoCyclePassingThrough(end->getNode());
86   return ret;
87 }
88
89 bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(Exception)
90 {
91   ComposedNode* father=checkHavingCommonFather(nodeS,nodeE);
92   if(father!=this)
93     {
94       checkInMyDescendance(father);
95       return father->edAddLink(nodeS->getOutGate(),nodeE->getInGate());
96     }
97   bool ret=nodeS->getOutGate()->edAddInGate(nodeE->getInGate());
98   if(ret)
99     checkNoCyclePassingThrough(nodeE);
100   return ret;
101 }
102
103 /**
104  * @ note : Remove a dataflow link.
105  *          Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
106  * @ exception : The specified link does not exist. The content of Exception is different in accordance with the link from 'start' to 'end' implies DF/DS gateway.
107  */
108 void ComposedNode::edRemoveLink(OutputPort *start, InputPort *end) throw(Exception)
109 {
110   ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
111   checkInMyDescendance(lwstCmnAnctr);
112   std::list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
113   std::list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
114   //Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
115   ComposedNode *iterS=start->getNode()->_father;
116   OutPort *currentPortO=start;
117   while(iterS!=lwstCmnAnctr)
118     {
119       currentPortO=iterS->getDelegateOf(currentPortO, allAscendanceOfNodeEnd);
120       iterS=iterS->_father;
121     }
122   iterS=end->getNode()->_father;
123   InPort *currentPortI=end;
124   while(iterS!=lwstCmnAnctr)
125     {
126       currentPortI=iterS->getDelegateOf(currentPortI, allAscendanceOfNodeStart);
127       iterS=iterS->_father;
128     }
129   //End of test for evt intermediate ports created
130   currentPortO->removeInPort(currentPortI);
131   //Performing deletion of intermediate ports
132   iterS=start->getNode()->_father;
133   currentPortO=start; currentPortI=end;
134   while(iterS!=lwstCmnAnctr)
135     {
136       currentPortO=iterS->releaseDelegateOf(currentPortO, allAscendanceOfNodeEnd);
137       iterS=iterS->_father;
138     }
139   iterS=end->getNode()->_father;
140   while(iterS!=lwstCmnAnctr)
141     {
142       currentPortI=iterS->releaseDelegateOf(currentPortI, allAscendanceOfNodeStart);
143       iterS=iterS->_father;
144     }
145 }
146
147 void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(Exception)
148 {
149   ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
150   if(father!=this)
151     throw Exception("edRemoveLink : nodes not in direct descendance of this");
152   start->edRemoveInGate(end);
153 }
154
155 void ComposedNode::publishOutputPort(OutputPort *port) throw(Exception)
156 {
157   checkInMyDescendance(port->getNode());
158   _listOfOutputPort.push_back(port);
159 }
160
161 void ComposedNode::publishInputPort(InputPort *port)
162 {
163   _listOfInputPort.push_back(port);
164 }
165
166 ComposedNode *ComposedNode::getRootNode() throw(Exception)
167 {
168   if(!_father)
169     return this;
170   return Node::getRootNode();
171 }
172
173 /**
174  * @ note : perform the disconnection of all links under the scope of 'this' connected to an input (dataflow or datastream) of node 'node'.
175  *          This method is quite heavy because the links are stored in one direction.
176  */
177 void ComposedNode::disconnectAllLinksConnectedTo(Node *node)
178 {
179   std::list<ElementaryNode *> listOfAllNodes=getRecursiveConstituents();
180   for(std::list<ElementaryNode *>::iterator iter=listOfAllNodes.begin();iter!=listOfAllNodes.end();iter++)
181     (*iter)->disconnectAllLinksConnectedTo(node);
182 }
183
184 /**
185  * @ note : Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
186  * @ exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
187  */
188 void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(Exception)
189 {
190   const char what[]="check failed : node is not in the correct descendance";
191   if(nodeToTest==0)
192     throw Exception(what);
193   if((ComposedNode *)nodeToTest==this)
194     return;
195   ComposedNode *iter=nodeToTest->_father;
196   while(iter!=0 && iter!=this)
197     iter=iter->_father;
198   if(iter==0)
199     throw Exception(what);
200 }
201
202 /**
203  *
204  * @ note : Retrieves the lowest common ancestor of 'node1' AND 'node2'. If 'node1' AND 'node2' are equals and are instance of ComposedNode 
205  *          the father of 'node1' is returned.
206  * @ exception : 'node1' and 'node2' does not share the same genealogy.
207  * @ return : The lowest common ancestor if it exists.
208  *
209  */
210 ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception)
211 {
212   const char what[]="2 nodes does not share the same genealogy";
213   if(node1==0 || node2==0)
214     throw Exception(what);
215   ComposedNode *temp=node1->_father;
216   std::set<ComposedNode *> s;
217   while(temp)
218     {
219       s.insert(temp);
220       temp=temp->_father;
221     }
222   //
223   temp=node2->_father;
224   std::set<ComposedNode *>::iterator iter=s.find(temp);
225   while(temp && iter==s.end())
226     {
227       iter=s.find(temp);
228       temp=temp->_father;
229     }
230   if(iter==s.end())
231     throw Exception(what);
232   return *iter;
233 }
234
235 /**
236  *
237  * @ note : Runtime called method. Perform, the state updating, from the son node 'node' emitting the event 'event' (among Executor static const var).
238  *          WARNING Precondition : this == node->_father
239  * @ return : The event (among Executor static const var) destinated to this->_father node to perform eventually up level update.
240  *
241  */
242 YACS::Event ComposedNode::updateStateFrom(Node *node,        //* I : node emitting event
243                                           YACS::Event event  //* I : event emitted
244                                           )
245 {
246   switch(event)
247     {
248     case YACS::START:
249       return updateStateOnStartEventFrom(node);
250       break;
251     case YACS::FINISH:
252       return updateStateOnFinishedEventFrom(node);
253       break;
254     default:
255       return YACS::NOEVENT;//TODO unexpected type of event
256       break;
257     }
258 }
259
260 InPort *ComposedNode::buildDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView)
261 {
262   return port;
263 }
264
265 OutPort *ComposedNode::buildDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView)
266 {
267   return port;
268 }
269
270 InPort *ComposedNode::getDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
271 {
272   return port;
273 }
274
275 OutPort *ComposedNode::getDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
276 {
277   return port;
278 }
279
280 InPort *ComposedNode::releaseDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
281 {
282   return port;
283 }
284
285 OutPort *ComposedNode::releaseDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
286 {
287   return port;
288 }