1 #include "ComposedNode.hxx"
2 #include "InputPort.hxx"
3 #include "OutputPort.hxx"
4 #include "ElementaryNode.hxx"
9 using namespace YACS::ENGINE;
12 ComposedNode::ComposedNode(const string& name):Node(name)
17 * A COMMENTER DAVANTAGE
18 * @note : Runtime called method. Overloads the Scheduler::notifyFrom abstract method.
19 * Typically Called in Executor (in a parallel thread or not) by the Task 'task'
20 * to inform the scheduler that an event coded 'event' (in Executor static const var) happened.
21 * Contrary to updateStateFrom several level may exist between 'sender' and 'this'.
24 void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
25 YACS::Event event //* I : event emitted
28 ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
29 //ASSERT(taskTyped != 0)
30 YACS::Event curEvent=event;
31 Node *lminus1LevelNode=taskTyped;
32 ComposedNode *curLevelNode=taskTyped->_father;
33 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
34 while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
36 lminus1LevelNode=curLevelNode;
37 curLevelNode=curLevelNode->_father;
38 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
43 * Add a dataflow link.
44 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
45 * @exception incompatibility between input and output (type), or 'start'/'end' is/are NOT in/outputPort
46 * contained in a node in descendance of 'this', or a multiple link to an input not supporting it.
47 * @return true if a new link has been created, false otherwise.
50 bool ComposedNode::edAddLink(OutputPort *start, InputPort *end) throw(Exception)
52 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
53 set<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
54 set<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
55 checkInMyDescendance(lwstCmnAnctr);
56 ComposedNode *iterS=start->getNode()->_father;
58 OutPort *currentPortO=start;
59 while(iterS!=lwstCmnAnctr)
61 currentPortO=iterS->buildDelegateOf(currentPortO, allAscendanceOfNodeStart);
64 iterS=end->getNode()->_father;
66 InPort *currentPortI=end;
67 while(iterS!=lwstCmnAnctr)
69 currentPortI=iterS->buildDelegateOf(currentPortI, allAscendanceOfNodeEnd);
73 bool linkDone = currentPortO->addInPort(currentPortI);
76 ComposedNode *iter=end->getNode()->_father;
79 iter->unpublishInputPort(end);
88 * @note : Add a controlflow link.
89 * Precondition : 'start' AND 'end' are in/outGate contained in a node in DIRECT descendance of 'this'.
90 * @exception : If a cycle has been detected, or incompatibility between input and output, or 'start'/'end' is/are NOT in/outputPort
91 * contained in a node in descendance of 'this', or a mutilple link to an input not supporting it.
92 * @return : true if a new link has been created, false otherwise.
94 bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(Exception)
96 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
99 checkInMyDescendance(father);
100 return father->edAddLink(start,end);
102 bool ret=start->edAddInGate(end);
104 checkNoCyclePassingThrough(end->getNode());
108 bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(Exception)
110 ComposedNode* father=checkHavingCommonFather(nodeS,nodeE);
113 checkInMyDescendance(father);
114 return father->edAddLink(nodeS->getOutGate(),nodeE->getInGate());
116 bool ret=nodeS->getOutGate()->edAddInGate(nodeE->getInGate());
118 checkNoCyclePassingThrough(nodeE);
123 * Remove a dataflow link.
124 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
125 * @exception The specified link does not exist.
126 * The content of Exception is different in accordance with the link from 'start' to 'end' implies DF/DS gateway.
129 void ComposedNode::edRemoveLink(OutputPort *start, InputPort *end) throw(Exception)
131 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
132 checkInMyDescendance(lwstCmnAnctr);
133 set<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
134 set<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
136 // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
138 ComposedNode *iterS=start->getNode()->_father;
139 OutPort *currentPortO=start;
140 while(iterS!=lwstCmnAnctr)
142 currentPortO=iterS->getDelegateOf(currentPortO, allAscendanceOfNodeEnd);
143 iterS=iterS->_father;
146 iterS=end->getNode()->_father;
147 InPort *currentPortI=end;
148 while(iterS!=lwstCmnAnctr)
150 currentPortI=iterS->getDelegateOf(currentPortI, allAscendanceOfNodeStart);
151 iterS=iterS->_father;
154 // --- End of test for evt intermediate ports created
156 currentPortO->removeInPort(currentPortI);
158 // --- Performing deletion of intermediate ports
160 iterS=start->getNode()->_father;
161 currentPortO=start; currentPortI=end;
162 while(iterS!=lwstCmnAnctr)
164 currentPortO=iterS->releaseDelegateOf(currentPortO, allAscendanceOfNodeEnd);
165 iterS=iterS->_father;
168 iterS=end->getNode()->_father;
169 while(iterS!=lwstCmnAnctr)
171 currentPortI=iterS->releaseDelegateOf(currentPortI, allAscendanceOfNodeStart);
172 iterS=iterS->_father;
175 // --- publish inputPort in ancestors
177 ComposedNode *iter=end->getNode()->_father;
180 iter->publishInputPort(end);
185 void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(Exception)
187 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
189 throw Exception("edRemoveLink : nodes not in direct descendance of this");
190 start->edRemoveInGate(end);
193 void ComposedNode::publishOutputPort(OutputPort *port) throw(Exception)
195 checkInMyDescendance(port->getNode());
196 _setOfOutputPort.insert(port);
199 void ComposedNode::publishInputPort(InputPort *port)
201 _setOfInputPort.insert(port);
204 void ComposedNode::unpublishInputPort(InputPort *port)
206 _setOfInputPort.erase(port);
210 ComposedNode *ComposedNode::getRootNode() throw(Exception)
214 return Node::getRootNode();
218 * @note : perform the disconnection of all links under the scope of 'this' connected to an input (dataflow or datastream) of node 'node'.
219 * This method is quite heavy because the links are stored in one direction.
221 void ComposedNode::disconnectAllLinksConnectedTo(Node *node)
223 set<ElementaryNode *> setOfAllNodes=getRecursiveConstituents();
224 for(set<ElementaryNode *>::iterator iter=setOfAllNodes.begin();iter!=setOfAllNodes.end();iter++)
225 (*iter)->disconnectAllLinksConnectedTo(node);
229 * @note : Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
230 * @exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
232 void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(Exception)
234 const char what[]="check failed : node is not in the correct descendance";
236 throw Exception(what);
237 if((ComposedNode *)nodeToTest==this)
239 ComposedNode *iter=nodeToTest->_father;
240 while(iter!=0 && iter!=this)
243 throw Exception(what);
248 * @note : Retrieves the lowest common ancestor of 'node1' AND 'node2'. If 'node1' AND 'node2' are equals and are instance of ComposedNode
249 * the father of 'node1' is returned.
250 * @exception : 'node1' and 'node2' does not share the same genealogy.
251 * @return : The lowest common ancestor if it exists.
254 ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception)
256 const char what[]="2 nodes does not share the same genealogy";
257 if(node1==0 || node2==0)
258 throw Exception(what);
259 ComposedNode *temp=node1->_father;
260 set<ComposedNode *> s;
268 set<ComposedNode *>::iterator iter=s.find(temp);
269 while(temp && iter==s.end())
275 throw Exception(what);
280 * get the input port name used by the current node, reursively built with children names.
283 const string ComposedNode::getInputPortName(const InputPort * inputPort) throw (Exception)
285 Node *node = inputPort->getNode();
286 string portName = inputPort->getName();
287 string nodeName = node->getName();
289 set<ComposedNode *> nodePortAncestors = node->getAllAscendanceOf();
291 if ( nodePortAncestors.find(this) == nodePortAncestors.end() )
293 string what("InputPort "); what+= portName; what+=" does not belong to node "; what += nodeName;
294 throw Exception(what);
298 while (father != this)
300 portName = father->getName() + '.' + portName;
301 father = father->_father;
306 const string ComposedNode::getOutputPortName(const OutputPort *outputPort) throw (Exception)
312 * @note : Runtime called method. Perform, the state updating, from the son node 'node' emitting the event 'event' (among Executor static const var).
313 * WARNING Precondition : this == node->_father
314 * @return : The event (among Executor static const var) destinated to this->_father node to perform eventually up level update.
317 YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
318 YACS::Event event //* I : event emitted
324 return updateStateOnStartEventFrom(node);
327 return updateStateOnFinishedEventFrom(node);
330 return YACS::NOEVENT;//TODO unexpected type of event
335 InPort *ComposedNode::buildDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfView)
340 OutPort *ComposedNode::buildDelegateOf(OutPort *port, const set<ComposedNode *>& pointsOfView)
345 InPort *ComposedNode::getDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)
350 OutPort *ComposedNode::getDelegateOf(OutPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)
355 InPort *ComposedNode::releaseDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)
360 OutPort *ComposedNode::releaseDelegateOf(OutPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)