Salome HOME
copy tag mergefrom_BR_V0_1_CC_Salome_04oct07
[modules/yacs.git] / src / engine / Loop.cxx
1 #include "Loop.hxx"
2 #include "InputPort.hxx"
3 #include "OutputPort.hxx"
4 #include "InputDataStreamPort.hxx"
5 #include "OutputDataStreamPort.hxx"
6 #include "Runtime.hxx"
7 #include "Visitor.hxx"
8 #include <cassert>
9 #include <iostream>
10
11 using namespace YACS::ENGINE;
12 using namespace std;
13
14 InputPort4DF2DS::InputPort4DF2DS(DFToDSForLoop *node, TypeCode* type):
15   InputPort("", node, type),
16   DataPort("", node, type),
17   Port(node),_data(0)
18 {
19 }
20
21 void InputPort4DF2DS::getAllRepresentants(std::set<InPort *>& repr) const
22 {
23   set<InPort *> s=_node->getOutputDataStreamPort("")->edSetInPort();
24   repr.insert(s.begin(),s.end());
25 }
26
27 void *InputPort4DF2DS::get() const throw(Exception)
28 {
29   if(!_data)
30     {
31       std::string what="InputPort4DF2DS::get : no value currently in input whith name \""; what+=_name; what+="\"";
32       throw Exception(what);
33     }
34   return (void *)_data;
35 }
36
37 void InputPort4DF2DS::exRestoreInit()
38 {
39   if(!_initValue)
40     return;
41   if(_data)
42     _data->decrRef();
43   _data=_initValue;
44   _data->incrRef();
45 }
46
47 void InputPort4DF2DS::exSaveInit()
48 {
49   if(_initValue)
50     _initValue->decrRef();
51   _initValue=_data;
52   _initValue->incrRef();
53 }
54
55 void InputPort4DF2DS::put(const void *data) throw(ConversionException)
56 {
57   put((Any *)data);
58 }
59
60 InputPort *InputPort4DF2DS::clone(Node *newHelder) const
61 {
62   throw Exception("InputPort4DF2DS::clone : internal error");
63 }
64
65 void InputPort4DF2DS::put(Any *data)
66 {
67   if(_data)
68     _data->decrRef();
69   _data=data;
70   _data->incrRef();
71 }
72
73 InputPort4DF2DS::~InputPort4DF2DS()
74 {
75   if(_data)
76     _data->decrRef();
77 }
78
79 DFToDSForLoop::DFToDSForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
80 {
81   _name="DF2DS For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
82   _father=loop;
83   _setOfInputPort.push_back(new InputPort4DF2DS(this,type));
84   _setOfOutputDataStreamPort.push_back(new OutputDataStreamPort("",this,Loop::MappingDF2DS(type)));
85 }
86
87 DFToDSForLoop::~DFToDSForLoop()
88 {
89 }
90
91 void DFToDSForLoop::getReadyTasks(std::vector<Task *>& tasks)
92 {
93 }
94
95 InputPort *DFToDSForLoop::getInputPort(const std::string& name) const throw(Exception)
96 {
97   list<InputPort *>::const_iterator it =_setOfInputPort.begin();
98   return (*it);
99 }
100
101 OutputDataStreamPort *DFToDSForLoop::getOutputDataStreamPort(const std::string& name) const throw(Exception)
102 {
103   list<OutputDataStreamPort *>::const_iterator it =_setOfOutputDataStreamPort.begin();
104   return (*it);
105 }
106
107 void DFToDSForLoop::load()
108 {
109 }
110
111 void DFToDSForLoop::execute()
112 {
113   //TO IMPLEMENT
114 }
115
116 Node *DFToDSForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
117 {
118   throw Exception("DFToDSForLoop::simpleClone : Internal error");
119 }
120
121 OutputPort4DS2DF::OutputPort4DS2DF(DSToDFForLoop *node, TypeCode *type):
122   OutputPort("", node, type),
123   DataPort("", node, type),
124   Port(node),_data(0)
125 {
126 }
127
128 void OutputPort4DS2DF::getAllRepresented(std::set<OutPort *>& represented) const
129 {
130   set<OutPort *> setO=_node->getInputDataStreamPort("")->edSetOutPort();
131   for(set<OutPort *>::iterator iter=setO.begin();iter!=setO.end();iter++)
132     (*iter)->getAllRepresented(represented);
133 }
134
135 void OutputPort4DS2DF::put(const void *data) throw(ConversionException)
136 {
137   put((Any *)data);
138   OutputPort::put(data);
139 }
140
141 OutputPort *OutputPort4DS2DF::clone(Node *newHelder) const
142 {
143   throw Exception("OutputPort4DS2DF::clone : Internal error");
144 }
145
146 void OutputPort4DS2DF::put(Any *data)
147 {
148   if(_data)
149     _data->decrRef();
150   _data=data;
151   _data->incrRef();
152 }
153
154 OutputPort4DS2DF::~OutputPort4DS2DF()
155 {
156   if(_data)
157     _data->decrRef();
158 }
159
160 InputDataStreamPort4DS2DF::InputDataStreamPort4DS2DF(DSToDFForLoop *node, TypeCode* type):
161   InputDataStreamPort("", node, type),
162   DataPort("", node, type),
163   Port(node)
164 {
165 }
166
167 void InputDataStreamPort4DS2DF::getAllRepresentants(std::set<InPort *>& repr) const
168 {
169   set<InPort *> s=_node->getOutputPort("")->edSetInPort();
170   repr.insert(s.begin(),s.end());
171 }
172
173 DSToDFForLoop::DSToDFForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
174 {
175   _name="DS2DF For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
176   _father=loop;
177   _setOfOutputPort.push_back(new OutputPort4DS2DF(this,type));
178   _setOfInputDataStreamPort.push_back(new InputDataStreamPort4DS2DF(this,type));
179 }
180
181 Node *DSToDFForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
182 {
183   throw Exception("DSToDFForLoop::simpleClone : Internal error");
184 }
185
186 DSToDFForLoop::~DSToDFForLoop()
187 {
188 }
189
190 void DSToDFForLoop::getReadyTasks(std::vector<Task *>& tasks)
191 {
192 }
193
194 OutputPort *DSToDFForLoop::getOutputPort(const std::string& name) const throw(Exception)
195 {
196   list<OutputPort *>::const_iterator it = _setOfOutputPort.begin();
197   return (*it);
198 }
199
200 InputDataStreamPort *DSToDFForLoop::getInputDataStreamPort(const std::string& name) const throw(Exception)
201 {
202   list<InputDataStreamPort *>::const_iterator it = _setOfInputDataStreamPort.begin();
203   return (*it);
204 }
205
206 void DSToDFForLoop::load()
207 {
208 }
209
210 void DSToDFForLoop::execute()
211 {
212   //TO IMPLEMENT
213 }
214
215 FakeNodeForLoop::FakeNodeForLoop(Loop *loop, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"),
216                                                                                     _loop(loop),
217                                                                                     _normalFinish(normalFinish),
218                                                                                     _internalError(internalError)
219 {
220   setState(YACS::TOACTIVATE);
221   _father=_loop->getFather();
222 }
223
224 FakeNodeForLoop::FakeNodeForLoop(const FakeNodeForLoop& other):ElementaryNode(other),_loop(0),
225                                                                _normalFinish(false),_internalError(true)
226 {
227 }
228
229 Node *FakeNodeForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
230 {
231   return new FakeNodeForLoop(*this);
232 }
233
234 void FakeNodeForLoop::exForwardFailed()
235 {
236   _loop->exForwardFailed();
237   FakeNodeForLoop *normallyThis=_loop->_nodeForNullTurnOfLoops;
238   _loop->_nodeForNullTurnOfLoops=0;
239   delete normallyThis;
240 }
241
242 void FakeNodeForLoop::exForwardFinished()
243
244   _loop->exForwardFinished();
245   FakeNodeForLoop *normallyThis=_loop->_nodeForNullTurnOfLoops;
246   _loop->_nodeForNullTurnOfLoops=0;
247   delete normallyThis;
248 }
249
250 void FakeNodeForLoop::execute()
251 {
252   if(!_normalFinish)
253     throw Exception("");//only to trigger ABORT on Executor
254 }
255
256 void FakeNodeForLoop::aborted()
257 {
258   if(_internalError)
259     _loop->setState(YACS::INTERNALERR);
260   else
261     _loop->setState(YACS::ERROR);
262 }
263
264 void FakeNodeForLoop::finished()
265 {
266   _loop->setState(YACS::DONE);
267 }
268
269 Loop::Loop(const Loop& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_nbOfTurns(0),_nodeForNullTurnOfLoops(0)
270 {
271   if(other._node)
272     _node=other._node->simpleClone(this,editionOnly);
273 }
274
275 Loop::Loop(const std::string& name):StaticDefinedComposedNode(name),_node(0),_nbOfTurns(0),_nodeForNullTurnOfLoops(0)
276 {
277 }
278
279 Loop::~Loop()
280 {
281   delete _node;
282   delete _nodeForNullTurnOfLoops;
283   for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
284     delete (*iter1);
285   for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
286     delete (*iter2);
287 }
288
289 void Loop::init(bool start)
290 {
291   StaticDefinedComposedNode::init(start);
292   _nbOfTurns=0;
293   if(_node)
294     _node->init(start); // if start is true, refresh the internal node
295   else
296     throw Exception("Loop::initLoop : no nodes specifies to be repeated ");
297   delete _nodeForNullTurnOfLoops;
298   _nodeForNullTurnOfLoops=0;
299 }
300
301 Node *Loop::edSetNode(Node *node)
302 {
303   if(_node==node)
304     return 0;
305   if(node)
306     {
307       if(node->_father)
308         {
309           string what = "Loop::edSetNode: node "; what += node->getName(); what += " is not orphan ! "; 
310           throw Exception(what);
311         }
312     }
313   StaticDefinedComposedNode::edRemoveChild(_node);
314   Node *ret=_node;
315   _node=node;
316   _node->_father=this;
317   return ret;
318 }
319
320 Node *Loop::edRemoveNode()
321 {
322   StaticDefinedComposedNode::edRemoveChild(_node);
323   Node *ret=_node;
324   _node=0;
325   return ret;
326 }
327
328 //! Collect all the child nodes that are ready
329 /*!
330  * \param tasks : vector of tasks to collect ready nodes
331  */
332 void Loop::getReadyTasks(std::vector<Task *>& tasks)
333 {
334   if(!_node)
335     return;
336   /*
337    * To change the way ComposedNode state is handled, uncomment the following line
338    * see Bloc::getReadyTasks
339    */
340   if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED);
341   if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
342     if(_nodeForNullTurnOfLoops)
343       _nodeForNullTurnOfLoops->getReadyTasks(tasks);
344     else
345       {
346         _node->getReadyTasks(tasks);
347         for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
348           (*iter1)->getReadyTasks(tasks);
349         for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
350           (*iter2)->getReadyTasks(tasks);
351       }
352 }
353
354 void Loop::edRemoveChild(Node *node) throw(Exception)
355 {
356   StaticDefinedComposedNode::edRemoveChild(node);
357   if(_node==node)
358     _node=0;
359 }
360
361 void Loop::selectRunnableTasks(std::vector<Task *>& tasks)
362 {
363 }
364
365 std::set<Node *> Loop::edGetDirectDescendants() const
366 {
367   set<Node *> ret;
368   if(_node)
369     ret.insert(_node);
370   return ret;
371 }
372
373 void Loop::checkConsistency(ComposedNode *pointOfView) const throw(Exception)
374 {
375 }
376
377 Node *Loop::getChildByShortName(const std::string& name) const throw(Exception)
378 {
379   if(name==_node->getName())
380     return _node;
381   string what("node "); what+= name ; what+=" is not a child of loop node "; what += getName();
382   throw Exception(what);
383 }
384
385 TypeCode* Loop::MappingDF2DS(TypeCode* type) throw(Exception)
386 {
387   return type;
388 }
389
390 TypeCode* Loop::MappingDS2DF(TypeCode* type) throw(Exception)
391 {
392   return type;
393 }
394
395 void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set<ComposedNode *>& pointsOfView)
396 {
397   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
398   if(typeOfPortInstance!=InputPort::NAME or
399      (typeOfPortInstance == InputPort::NAME and 
400       initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME and 
401       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
402     return ;
403   InputPort *portCasted=(InputPort *)port;
404   set<DSToDFForLoop*>::iterator iter;
405   //Determinig if a DSToDFForLoop node has already been created for delegation of 'port'
406   for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
407     if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
408       break;
409   if(iter==_inputsTraducer.end())
410     {//first time that 'port' is delegated on higher level
411       pair<set<DSToDFForLoop*>::iterator, bool> iter2=_inputsTraducer.insert(new DSToDFForLoop(this,portCasted->getName(),Loop::MappingDF2DS(portCasted->edGetType())));
412       iter=iter2.first;
413       (*iter)->getOutputPort("")->addInPort(portCasted);
414     }
415   else
416     (*iter)->loopHasOneMoreRef();
417   port=(*iter)->getInputDataStreamPort("");
418 }
419
420 void Loop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::set<ComposedNode *>& pointsOfView)
421 {
422   string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
423   if(typeOfPortInstance!=OutputPort::NAME or
424     ( typeOfPortInstance == OutputPort::NAME and 
425       finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME and 
426       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
427     return ;
428   OutPort *portCasted=port.first;
429   set<DFToDSForLoop*>::iterator iter;
430   //Determinig if a DFToDSForLoop node has already been created for delegation of 'port'
431   for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
432     if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
433       break;
434   DFToDSForLoop *kl;
435   if(iter==_outputsTraducer.end())
436     {//first time that 'port' is delegated on higher level
437       //_outputsTraducer.insert(new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType()));
438       kl=new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType());
439       pair<set<DFToDSForLoop*>::iterator, bool> iter2=_outputsTraducer.insert(kl);
440       iter=iter2.first;
441       portCasted->addInPort((*iter)->getInputPort(""));
442     }
443   else
444     {
445       kl=*iter;
446       kl->loopHasOneMoreRef();
447     }
448   edAddLink(isInMyDescendance((port.first)->getNode())->getOutGate(),kl->getInGate());
449   port.first=(*iter)->getOutputDataStreamPort("");
450 }
451
452 void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::set<ComposedNode *>& pointsOfView) throw(Exception)
453 {
454   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
455   if(typeOfPortInstance!=InputPort::NAME or
456      (typeOfPortInstance == InputPort::NAME and 
457       initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME and 
458       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
459     return ;
460   InputPort *portCasted=(InputPort *)port;
461   set<DSToDFForLoop*>::iterator iter;
462   for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
463     if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
464       break;
465   if(iter==_inputsTraducer.end())
466     {
467       string what("Loop::getDelegateOf : Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
468       throw Exception(what);
469     }
470   else
471     port=(*iter)->getInputDataStreamPort("");
472 }
473
474 void Loop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, 
475                          const std::set<ComposedNode *>& pointsOfView) throw(Exception)
476 {
477   string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
478   if(typeOfPortInstance!=OutputPort::NAME or
479     ( typeOfPortInstance == OutputPort::NAME and 
480       finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME and 
481       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
482     return ;
483   OutPort *portCasted=port.first;
484   set<DFToDSForLoop*>::iterator iter;
485   for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
486     if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
487       break;
488   if(iter==_outputsTraducer.end())
489     {
490       string what("Loop::getDelegateOf : Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
491       throw Exception(what);
492     }
493   else
494     port.first=(*iter)->getOutputDataStreamPort("");
495 }
496
497 void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::set<ComposedNode *>& pointsOfView) throw(Exception)
498 {
499   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
500   if(typeOfPortInstance!=InputPort::NAME or
501     ( typeOfPortInstance == InputPort::NAME and 
502       initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME and 
503       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
504     return ;
505   InputPort *portCasted=(InputPort *)port;
506   set<DSToDFForLoop*>::iterator iter;
507   for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
508     if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
509       break;
510   if(iter==_inputsTraducer.end())
511     {
512       string what("Loop::releaseDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
513       throw Exception(what);
514     }
515   else
516     {
517       port=(*iter)->getInputDataStreamPort("");
518       if((*iter)->loopHasOneLessRef())
519         {
520           (*iter)->getOutputPort("")->removeInPort(portCasted,false);
521           delete (*iter);
522           _inputsTraducer.erase(iter);
523         }
524     }
525 }
526
527 void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set<ComposedNode *>& pointsOfView) throw(Exception)
528 {
529   if(portDwn==portUp)
530     return ;
531   set<DFToDSForLoop*>::iterator iter;
532   for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
533     if((*iter)->getOutputDataStreamPort("")==portUp)
534       break;
535   if((*iter)->loopHasOneLessRef())
536     {
537       portDwn->removeInPort((*iter)->getInputPort(""),false);
538       delete (*iter);
539       _outputsTraducer.erase(iter);
540     }
541 }
542
543 void Loop::checkNoCyclePassingThrough(Node *node) throw(Exception)
544 {
545   //throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured");
546 }
547
548 /*!
549  * \note : States if a DF port must be considered on an upper level in hierarchy as a DS port or not from 'pointsOfView' observers.
550  * \return : 
551  *            - True : a traduction DF->DS has to be done
552  *            - False : no traduction needed
553  */
554 bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::set<ComposedNode *>& pointsOfView)
555 {
556   bool ret=false;
557   for(set<ComposedNode *>::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++)
558     ret=(*iter)->isRepeatedUnpredictablySeveralTimes();
559   return ret;
560 }
561
562 //! Connect an OutPort to an InPort and add control link if necessary
563 /*!
564  * Connect the ports with a data link (edAddLink) 
565  * In a Loop don't add control flow link : use this only to add data back links
566  *
567  * \param start : the OutPort to connect
568  * \param end : the InPort to connect
569  * \return  true if a new link has been created, false otherwise.
570  */
571 bool Loop::edAddDFLink(OutPort *start, InPort *end) throw(Exception)
572 {
573   return edAddLink(start,end);
574 }
575
576 //! Dump the node state to a stream
577 /*!
578  * \param os : the output stream
579  */
580 void Loop::writeDot(std::ostream &os)
581 {
582   os << "  subgraph cluster_" << getId() << "  {\n" ;
583   //only one node in a loop
584   _node->writeDot(os);
585   os << getId() << " -> " << _node->getId() << ";\n";
586   os << "}\n" ;
587   os << getId() << "[fillcolor=\"" ;
588   YACS::StatesForNode state=getEffectiveState();
589   os << getColorState(state);
590   os << "\" label=\"" << "Loop:" ;
591   os << getQualifiedName() <<"\"];\n";
592 }
593
594
595 void Loop::accept(Visitor *visitor)
596 {
597   visitor->visitLoop(this);
598 }
599
600 /*!
601  *  For use only when loading a previously saved execution
602  */
603
604 void YACS::ENGINE::NbDoneLoader(Loop* node, int val)
605 {
606   node->_nbOfTurns = val;
607 }