Version: 8.3.0
Loop.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 
20 #include "Loop.hxx"
21 #include "InputPort.hxx"
22 #include "OutputPort.hxx"
23 #include "InputDataStreamPort.hxx"
24 #include "OutputDataStreamPort.hxx"
25 #include "LinkInfo.hxx"
26 #include "Runtime.hxx"
27 #include "Visitor.hxx"
28 #include <cassert>
29 #include <iostream>
30 
31 //#define _DEVDEBUG_
32 #include "YacsTrace.hxx"
33 
34 using namespace YACS::ENGINE;
35 using namespace std;
36 
38  InputPort("", node, type),
39  DataPort("", node, type),
40  Port(node),_data(0)
41 {
42 }
43 
44 void InputPort4DF2DS::getAllRepresentants(std::set<InPort *>& repr) const
45 {
46  set<InPort *> s=_node->getOutputDataStreamPort("")->edSetInPort();
47  repr.insert(s.begin(),s.end());
48 }
49 
50 void *InputPort4DF2DS::get() const throw(YACS::Exception)
51 {
52  if(!_data)
53  {
54  std::string what="InputPort4DF2DS::get : no value currently in input whith name \""; what+=_name; what+="\"";
55  throw Exception(what);
56  }
57  return (void *)_data;
58 }
59 
61 {
62  if(!_initValue)
63  return;
64  if(_data)
65  _data->decrRef();
67  _data->incrRef();
68 }
69 
71 {
72  if(_initValue)
76 }
77 
78 void InputPort4DF2DS::put(const void *data) throw(ConversionException)
79 {
80  put((Any *)data);
81 }
82 
84 {
85  throw Exception("InputPort4DF2DS::clone : internal error");
86 }
87 
89 {
90  if(_data)
91  _data->decrRef();
92  _data=data;
93  _data->incrRef();
94 }
95 
97 {
98  if(_data)
99  _data->decrRef();
100 }
101 
102 DFToDSForLoop::DFToDSForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
103 {
104  _name="DF2DS For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
105  _father=loop;
106  _setOfInputPort.push_back(new InputPort4DF2DS(this,type));
108 }
109 
111 {
113 }
114 
115 void DFToDSForLoop::getReadyTasks(std::vector<Task *>& tasks)
116 {
117 }
118 
119 InputPort *DFToDSForLoop::getInputPort(const std::string& name) const throw(YACS::Exception)
120 {
121  try {
122  return Node::getInputPort(name);
123  }
124  catch(Exception& e) {}
125 
126  list<InputPort *>::const_iterator it =_setOfInputPort.begin();
127  return (*it);
128 }
129 
131 {
132  list<OutputDataStreamPort *>::const_iterator it =_setOfOutputDataStreamPort.begin();
133  return (*it);
134 }
135 
137 {
138 }
139 
141 {
142  //TO IMPLEMENT
143 }
144 
145 Node *DFToDSForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
146 {
147  throw Exception("DFToDSForLoop::simpleClone : Internal error");
148 }
149 
151  OutputPort("", node, type),
152  DataPort("", node, type),
153  Port(node),_data(0)
154 {
155 }
156 
157 void OutputPort4DS2DF::getAllRepresented(std::set<OutPort *>& represented) const
158 {
159  set<OutPort *> setO=_node->getInputDataStreamPort("")->edSetOutPort();
160  for(set<OutPort *>::iterator iter=setO.begin();iter!=setO.end();iter++)
161  (*iter)->getAllRepresented(represented);
162 }
163 
164 void OutputPort4DS2DF::put(const void *data) throw(ConversionException)
165 {
166  put((Any *)data);
167  OutputPort::put(data);
168 }
169 
171 {
172  throw Exception("OutputPort4DS2DF::clone : Internal error");
173 }
174 
176 {
177  if(_data)
178  _data->decrRef();
179  _data=data;
180  _data->incrRef();
181 }
182 
184 {
185  if(_data)
186  _data->decrRef();
187 }
188 
190  InputDataStreamPort("", node, type),
191  DataPort("", node, type),
192  Port(node)
193 {
194 }
195 
196 void InputDataStreamPort4DS2DF::getAllRepresentants(std::set<InPort *>& repr) const
197 {
198  set<InPort *> s=_node->getOutputPort("")->edSetInPort();
199  repr.insert(s.begin(),s.end());
200 }
201 
202 DSToDFForLoop::DSToDFForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
203 {
204  _name="DS2DF For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
205  _father=loop;
206  _setOfOutputPort.push_back(new OutputPort4DS2DF(this,type));
207  _setOfInputDataStreamPort.push_back(new InputDataStreamPort4DS2DF(this,type));
208 }
209 
210 Node *DSToDFForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
211 {
212  throw Exception("DSToDFForLoop::simpleClone : Internal error");
213 }
214 
216 {
218 }
219 
220 void DSToDFForLoop::getReadyTasks(std::vector<Task *>& tasks)
221 {
222 }
223 
224 OutputPort *DSToDFForLoop::getOutputPort(const std::string& name) const throw(YACS::Exception)
225 {
226  list<OutputPort *>::const_iterator it = _setOfOutputPort.begin();
227  return (*it);
228 }
229 
231 {
232  list<InputDataStreamPort *>::const_iterator it = _setOfInputDataStreamPort.begin();
233  return (*it);
234 }
235 
237 {
238 }
239 
241 {
242  //TO IMPLEMENT
243 }
244 
245 FakeNodeForLoop::FakeNodeForLoop(Loop *loop, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"),
246  _loop(loop),
247  _normalFinish(normalFinish),
248  _internalError(internalError)
249 {
252 }
253 
255  _normalFinish(false),_internalError(true)
256 {
257 }
258 
259 Node *FakeNodeForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
260 {
261  return new FakeNodeForLoop(*this);
262 }
263 
265 {
267 }
268 
270 {
272 }
273 
275 {
276  if(!_normalFinish)
277  throw Exception("");//only to trigger ABORT on Executor
278 }
279 
281 {
282  if(_internalError)
284  else
286 }
287 
289 {
291 }
292 
293 Loop::Loop(const Loop& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_nbOfTurns(0),_nodeForNullTurnOfLoops(0),_node(0)
294 {
295  if(other._node)
296  _node=other._node->simpleClone(this,editionOnly);
297 }
298 
299 Loop::Loop(const std::string& name):StaticDefinedComposedNode(name),_node(0),_nbOfTurns(0),_nodeForNullTurnOfLoops(0)
300 {
301 }
302 
304 {
305  delete _node;
307  for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
308  delete (*iter1);
309  for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
310  delete (*iter2);
311 }
312 
313 void Loop::init(bool start)
314 {
316  _nbOfTurns=0;
317  if(_node)
318  _node->init(start); // if start is true, refresh the internal node
319  else
320  throw Exception("Loop::initLoop : no nodes specifies to be repeated ");
323 }
324 
326 {
327  if(_node==node)
328  return 0;
329  if(node)
330  {
331  if(node->_father)
332  {
333  string what = "Loop::edSetNode: node "; what += node->getName(); what += " is not orphan ! ";
334  throw Exception(what);
335  }
336  }
339  Node *ret=_node;
340  _node=node;
341  _node->_father=this;
342  //set _modified flag so that edUpdateState() can refresh state
343  modified();
344  return ret;
345 }
346 
348 {
349  return edSetNode(node);
350 }
351 
353 {
355  Node *ret=_node;
356  _node=0;
357  modified();
358  return ret;
359 }
360 
362 
365 void Loop::getReadyTasks(std::vector<Task *>& tasks)
366 {
367  if(!_node)
368  return;
369  /*
370  * To change the way ComposedNode state is handled, uncomment the following line
371  * see Bloc::getReadyTasks
372  */
377  else
378  {
379  _node->getReadyTasks(tasks);
380  for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
381  (*iter1)->getReadyTasks(tasks);
382  for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
383  (*iter2)->getReadyTasks(tasks);
384  }
385 }
386 
388 {
390  if(_node==node)
391  _node=0;
392  modified();
393 }
394 
395 std::list<Node *> Loop::edGetDirectDescendants() const
396 {
397  list<Node *> ret;
398  if(_node)
399  ret.push_back(_node);
400  return ret;
401 }
402 
403 std::list<InputPort *> Loop::getSetOfInputPort() const
404 {
406  ret.push_back(getDecisionPort());
407  return ret;
408 }
409 
411 {
413 }
414 
416 {
417  if(!_node)
418  return 0;
420 }
421 
422 Node *Loop::getChildByShortName(const std::string& name) const throw(YACS::Exception)
423 {
424  if (_node)
425  if(name==_node->getName())
426  return _node;
427  string what("node "); what+= name ; what+=" is not a child of loop node "; what += getName();
428  throw Exception(what);
429 }
430 
432 {
433  return type;
434 }
435 
437 {
438  return type;
439 }
440 
441 void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
442 {
443  string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
444  if(typeOfPortInstance!=InputPort::NAME ||
445  (typeOfPortInstance == InputPort::NAME &&
448  return ;
449  InputPort *portCasted=(InputPort *)port;
450  set<DSToDFForLoop*>::iterator iter;
451  //Determinig if a DSToDFForLoop node has already been created for delegation of 'port'
452  for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
453  if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
454  break;
455  if(iter==_inputsTraducer.end())
456  {//first time that 'port' is delegated on higher level
457  pair<set<DSToDFForLoop*>::iterator, bool> iter2=_inputsTraducer.insert(new DSToDFForLoop(this,portCasted->getName(),Loop::MappingDF2DS(portCasted->edGetType())));
458  iter=iter2.first;
459  (*iter)->getOutputPort("")->addInPort(portCasted);
460  }
461  else
462  (*iter)->loopHasOneMoreRef();
463  port=(*iter)->getInputDataStreamPort("");
464 }
465 
466 void Loop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
467 {
468  string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
469  if(typeOfPortInstance!=OutputPort::NAME ||
470  ( typeOfPortInstance == OutputPort::NAME &&
473  return ;
474  OutPort *portCasted=port.first;
475  set<DFToDSForLoop*>::iterator iter;
476  //Determinig if a DFToDSForLoop node has already been created for delegation of 'port'
477  for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
478  if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
479  break;
480  DFToDSForLoop *kl;
481  if(iter==_outputsTraducer.end())
482  {//first time that 'port' is delegated on higher level
483  //_outputsTraducer.insert(new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType()));
484  kl=new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType());
485  pair<set<DFToDSForLoop*>::iterator, bool> iter2=_outputsTraducer.insert(kl);
486  iter=iter2.first;
487  portCasted->addInPort((*iter)->getInputPort(""));
488  }
489  else
490  {
491  kl=*iter;
492  kl->loopHasOneMoreRef();
493  }
494  edAddLink(isInMyDescendance((port.first)->getNode())->getOutGate(),kl->getInGate());
495  port.first=(*iter)->getOutputDataStreamPort("");
496 }
497 
498 void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
499 {
500  string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
501  if(typeOfPortInstance!=InputPort::NAME ||
502  (typeOfPortInstance == InputPort::NAME &&
503  initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME &&
504  !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
505  return ;
506  InputPort *portCasted=(InputPort *)port;
507  set<DSToDFForLoop*>::iterator iter;
508  for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
509  if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
510  break;
511  if(iter==_inputsTraducer.end())
512  {
513  string what("Loop::getDelegateOf : Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
514  throw Exception(what);
515  }
516  else
517  port=(*iter)->getInputDataStreamPort("");
518 }
519 
520 void Loop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget,
521  const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
522 {
523  string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
524  if(typeOfPortInstance!=OutputPort::NAME ||
525  ( typeOfPortInstance == OutputPort::NAME &&
526  finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME &&
527  !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
528  return ;
529  OutPort *portCasted=port.first;
530  set<DFToDSForLoop*>::iterator iter;
531  for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
532  if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
533  break;
534  if(iter==_outputsTraducer.end())
535  {
536  string what("Loop::getDelegateOf : Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
537  throw Exception(what);
538  }
539  else
540  port.first=(*iter)->getOutputDataStreamPort("");
541 }
542 
543 void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
544 {
545  string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
546  if(typeOfPortInstance!=InputPort::NAME ||
547  ( typeOfPortInstance == InputPort::NAME &&
548  initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME &&
549  !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
550  return ;
551  InputPort *portCasted=(InputPort *)port;
552  set<DSToDFForLoop*>::iterator iter;
553  for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
554  if((*iter)->getOutputPort("")->isAlreadyInSet(portCasted))
555  break;
556  if(iter==_inputsTraducer.end())
557  {
558  string what("Loop::releaseDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
559  throw Exception(what);
560  }
561  else
562  {
563  port=(*iter)->getInputDataStreamPort("");
564  if((*iter)->loopHasOneLessRef())
565  {
566  (*iter)->getOutputPort("")->removeInPort(portCasted,false);
567  delete (*iter);
568  _inputsTraducer.erase(iter);
569  }
570  }
571 }
572 
573 void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
574 {
575  if(portDwn==portUp)
576  return ;
577  set<DFToDSForLoop*>::iterator iter;
578  for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
579  if((*iter)->getOutputDataStreamPort("")==portUp)
580  break;
581  if((*iter)->loopHasOneLessRef())
582  {
583  portDwn->removeInPort((*iter)->getInputPort(""),false);
584  delete (*iter);
585  _outputsTraducer.erase(iter);
586  }
587 }
588 
590 {
591  //throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured");
592 }
593 
594 void Loop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
595 {
596  Node *nodeEnd=end->getNode();
597  if(nodeEnd==this)
598  {//In this case 'end' port is a special port of this (for exemple ForLoop::_nbOfTimesPort)
599  //ASSERT(!direction) see Loop::checkControlDependancy (bw only)
600  solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
601  }
602  else
603  StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info);
604 }
605 
612 bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::list<ComposedNode *>& pointsOfView)
613 {
614  bool ret=false;
615  for(list<ComposedNode *>::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++)
616  ret=(*iter)->isRepeatedUnpredictablySeveralTimes();
617  return ret;
618 }
619 
621 
630 {
631  return edAddLink(start,end);
632 }
633 
635 
638 void Loop::writeDot(std::ostream &os) const
639 {
640  os << " subgraph cluster_" << getId() << " {\n" ;
641  //only one node in a loop
642  if(_node)
643  {
644  _node->writeDot(os);
645  os << getId() << " -> " << _node->getId() << ";\n";
646  }
647  os << "}\n" ;
648  os << getId() << "[fillcolor=\"" ;
650  os << getColorState(state);
651  os << "\" label=\"" << "Loop:" ;
652  os << getQualifiedName() <<"\"];\n";
653 }
654 
655 
656 void Loop::accept(Visitor *visitor)
657 {
658  visitor->visitLoop(this);
659 }
660 
661 void Loop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
662  std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
663  std::vector<OutPort *>& fwCross,
664  std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
665  LinkInfo& info) const
666 {
667  //First testing if end==getDecisionPort. This is the only case possible in theory.
668  if(end!=getDecisionPort())
669  return StaticDefinedComposedNode::checkControlDependancy(start,end,cross,fw,fwCross,bw,info);
670  if(cross)
671  throw Exception("Internal error occured - cross type link detected on decision port of a loop. Forbidden !");
672  fw[(ComposedNode *)this].push_back(start);
673 }
674 
676 {
677  DEBTRACE("Loop::checkBasicConsistency");
679  if(!_node)
680  throw Exception("For a loop, internal node is mandatory");
681 }
682 
687 void YACS::ENGINE::NbDoneLoader(Loop* node, int val)
688 {
689  node->_nbOfTurns = val;
690 }