Salome HOME
Copyright update 2022
[modules/yacs.git] / src / engine / Loop.cxx
index b9a2960b72820775db7e00e93a7beb5b142714c5..325a05f9a01120f1df46e0e4a04c6237e7e90d7b 100644 (file)
+// Copyright (C) 2006-2022  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
 #include "Loop.hxx"
 #include "InputPort.hxx"
 #include "OutputPort.hxx"
 #include "InputDataStreamPort.hxx"
 #include "OutputDataStreamPort.hxx"
+#include "LinkInfo.hxx"
 #include "Runtime.hxx"
+#include "Visitor.hxx"
+#include <cassert>
+#include <iostream>
 
-//#include "TypeCheckerDataStream.hxx"
+//#define _DEVDEBUG_
+#include "YacsTrace.hxx"
 
 using namespace YACS::ENGINE;
 using namespace std;
 
-DFToDSForLoop::DFToDSForLoop(Loop *loop, const string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
+InputPort4DF2DS::InputPort4DF2DS(DFToDSForLoop *node, TypeCode* type):
+  InputPort("", node, type),
+  DataPort("", node, type),
+  Port(node),_data(0)
+{
+}
+
+void InputPort4DF2DS::getAllRepresentants(std::set<InPort *>& repr) const
+{
+  set<InPort *> s=_node->getOutputDataStreamPort("")->edSetInPort();
+  repr.insert(s.begin(),s.end());
+}
+
+void *InputPort4DF2DS::get() const
+{
+  if(!_data)
+    {
+      std::string what="InputPort4DF2DS::get : no value currently in input whith name \""; what+=_name; what+="\"";
+      throw Exception(what);
+    }
+  return (void *)_data;
+}
+
+void InputPort4DF2DS::exRestoreInit()
+{
+  if(!_initValue)
+    return;
+  if(_data)
+    _data->decrRef();
+  _data=_initValue;
+  _data->incrRef();
+}
+
+void InputPort4DF2DS::exSaveInit()
+{
+  if(_initValue)
+    _initValue->decrRef();
+  _initValue=_data;
+  _initValue->incrRef();
+}
+
+void InputPort4DF2DS::put(const void *data)
+{
+  put((Any *)data);
+}
+
+InputPort *InputPort4DF2DS::clone(Node *newHelder) const
+{
+  throw Exception("InputPort4DF2DS::clone : internal error");
+}
+
+void InputPort4DF2DS::releaseData()
+{
+  if(_data)
+    _data->decrRef();
+  _data = nullptr;
+}
+
+void InputPort4DF2DS::put(Any *data)
+{
+  InputPort4DF2DS::releaseData();
+  _data=data;
+  _data->incrRef();
+}
+
+InputPort4DF2DS::~InputPort4DF2DS()
+{
+  if(_data)
+    _data->decrRef();
+}
+
+DFToDSForLoop::DFToDSForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
 {
   _name="DF2DS For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
   _father=loop;
-//   _setOfInputPort.insert(new InputPort("",this,type)); // probleme si constructeur protege, a voir
-  _setOfOutputDataStreamPort.insert(new OutputDataStreamPort("",this,Loop::MappingDF2DS(type)));
+  _setOfInputPort.push_back(new InputPort4DF2DS(this,type));
+  _setOfOutputDataStreamPort.push_back(new OutputDataStreamPort("",this,Loop::MappingDF2DS(type)));
 }
 
 DFToDSForLoop::~DFToDSForLoop()
+{
+  edDisconnectAllLinksWithMe();
+}
+
+void DFToDSForLoop::getReadyTasks(std::vector<Task *>& tasks)
 {
 }
 
-InputPort *DFToDSForLoop::getInputPort(const string& name) const throw(Exception)
+InputPort *DFToDSForLoop::getInputPort(const std::string& name) const
 {
-  set<InputPort *>::iterator it =_setOfInputPort.begin();
+  try {
+    return Node::getInputPort(name);
+  }
+  catch(Exception& e) {}
+
+  list<InputPort *>::const_iterator it =_setOfInputPort.begin();
   return (*it);
 }
 
-OutputDataStreamPort *DFToDSForLoop::getOutputDataStreamPort(const string& name) const throw(Exception)
+OutputDataStreamPort *DFToDSForLoop::getOutputDataStreamPort(const std::string& name) const
 {
-  set<OutputDataStreamPort *> ::iterator it =_setOfOutputDataStreamPort.begin();
+  list<OutputDataStreamPort *>::const_iterator it =_setOfOutputDataStreamPort.begin();
   return (*it);
 }
 
+void DFToDSForLoop::load()
+{
+}
+
 void DFToDSForLoop::execute()
 {
   //TO IMPLEMENT
 }
 
-DSToDFForLoop::DSToDFForLoop(Loop *loop, const string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
+Node *DFToDSForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
+{
+  throw Exception("DFToDSForLoop::simpleClone : Internal error");
+}
+
+OutputPort4DS2DF::OutputPort4DS2DF(DSToDFForLoop *node, TypeCode *type):
+  OutputPort("", node, type),
+  DataPort("", node, type),
+  Port(node),_data(0)
+{
+}
+
+void OutputPort4DS2DF::getAllRepresented(std::set<OutPort *>& represented) const
+{
+  set<OutPort *> setO=_node->getInputDataStreamPort("")->edSetOutPort();
+  for(set<OutPort *>::iterator iter=setO.begin();iter!=setO.end();iter++)
+    (*iter)->getAllRepresented(represented);
+}
+
+void OutputPort4DS2DF::put(const void *data)
+{
+  put((Any *)data);
+  OutputPort::put(data);
+}
+
+OutputPort *OutputPort4DS2DF::clone(Node *newHelder) const
+{
+  throw Exception("OutputPort4DS2DF::clone : Internal error");
+}
+
+void OutputPort4DS2DF::put(Any *data)
+{
+  if(_data)
+    _data->decrRef();
+  _data=data;
+  _data->incrRef();
+}
+
+OutputPort4DS2DF::~OutputPort4DS2DF()
+{
+  if(_data)
+    _data->decrRef();
+}
+
+InputDataStreamPort4DS2DF::InputDataStreamPort4DS2DF(DSToDFForLoop *node, TypeCode* type):
+  InputDataStreamPort("", node, type),
+  DataPort("", node, type),
+  Port(node)
+{
+}
+
+void InputDataStreamPort4DS2DF::getAllRepresentants(std::set<InPort *>& repr) const
+{
+  set<InPort *> s=_node->getOutputPort("")->edSetInPort();
+  repr.insert(s.begin(),s.end());
+}
+
+DSToDFForLoop::DSToDFForLoop(Loop *loop, const std::string& name, TypeCode* type):ElementaryNode(""),_nbOfTimeUsed(1)
 {
   _name="DS2DF For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
   _father=loop;
-  //  _setOfOutputPort.insert(new OutputPort("",this,Loop::MappingDS2DF(type))); // probleme si constructeur protege, a voir
-  _setOfInputDataStreamPort.insert(new InputDataStreamPort("",this,type));
+  _setOfOutputPort.push_back(new OutputPort4DS2DF(this,type));
+  _setOfInputDataStreamPort.push_back(new InputDataStreamPort4DS2DF(this,type));
+}
+
+Node *DSToDFForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
+{
+  throw Exception("DSToDFForLoop::simpleClone : Internal error");
 }
 
 DSToDFForLoop::~DSToDFForLoop()
+{
+  edDisconnectAllLinksWithMe();
+}
+
+void DSToDFForLoop::getReadyTasks(std::vector<Task *>& tasks)
 {
 }
 
-OutputPort *DSToDFForLoop::getOutputPort(const string& name) const throw(Exception)
+OutputPort *DSToDFForLoop::getOutputPort(const std::string& name) const
 {
-  set<OutputPort *>::iterator it = _setOfOutputPort.begin();
+  list<OutputPort *>::const_iterator it = _setOfOutputPort.begin();
   return (*it);
 }
 
-InputDataStreamPort *DSToDFForLoop::getInputDataStreamPort(const string& name) const throw(Exception)
+InputDataStreamPort *DSToDFForLoop::getInputDataStreamPort(const std::string& name) const
 {
-  set<InputDataStreamPort *>::iterator it = _setOfInputDataStreamPort.begin();
+  list<InputDataStreamPort *>::const_iterator it = _setOfInputDataStreamPort.begin();
   return (*it);
 }
 
+void DSToDFForLoop::load()
+{
+}
+
 void DSToDFForLoop::execute()
 {
   //TO IMPLEMENT
 }
 
-Loop::Loop(const string& name):ComposedNode(name),_node(0)
+FakeNodeForLoop::FakeNodeForLoop(Loop *loop, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"),
+                                                                                    _loop(loop),
+                                                                                    _normalFinish(normalFinish),
+                                                                                    _internalError(internalError)
+{
+  setState(YACS::TOACTIVATE);
+  _father=_loop->getFather();
+}
+
+FakeNodeForLoop::FakeNodeForLoop(const FakeNodeForLoop& other):ElementaryNode(other),_loop(0),
+                                                               _normalFinish(false),_internalError(true)
+{
+}
+
+Node *FakeNodeForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
+{
+  return new FakeNodeForLoop(*this);
+}
+
+void FakeNodeForLoop::exForwardFailed()
+{
+  _loop->exForwardFailed();
+}
+
+void FakeNodeForLoop::exForwardFinished()
+{ 
+  _loop->exForwardFinished();
+}
+
+void FakeNodeForLoop::execute()
+{
+  if(!_normalFinish)
+    throw Exception("");//only to trigger ABORT on Executor
+}
+
+void FakeNodeForLoop::aborted()
+{
+  if(_internalError)
+    _loop->setState(YACS::INTERNALERR);
+  else
+    _loop->setState(YACS::ERROR);
+}
+
+void FakeNodeForLoop::finished()
+{
+  _loop->setState(YACS::DONE);
+}
+
+Loop::Loop(const Loop& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_nbOfTurns(0),_nodeForNullTurnOfLoops(0),_node(0)
+{
+  if(other._node)
+    _node=other._node->simpleClone(this,editionOnly);
+}
+
+Loop::Loop(const std::string& name):StaticDefinedComposedNode(name),_node(0),_nbOfTurns(0),_nodeForNullTurnOfLoops(0)
 {
 }
 
 Loop::~Loop()
 {
   delete _node;
+  if(_nodeForNullTurnOfLoops)delete _nodeForNullTurnOfLoops;
+  for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
+    delete (*iter1);
+  for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
+    delete (*iter2);
 }
 
-void Loop::edSetNode(Node *node)
+void Loop::init(bool start)
 {
-  delete _node;
-  _node=node;
+  StaticDefinedComposedNode::init(start);
+  _nbOfTurns=0;
+  if(_node)
+    _node->init(start); // if start is true, refresh the internal node
+  else
+    throw Exception("Loop::initLoop : no nodes specifies to be repeated ");
+  delete _nodeForNullTurnOfLoops;
+  _nodeForNullTurnOfLoops=0;
 }
 
-void Loop::edAddExtraInputPort(const string& inputPortName, TypeCode* type) throw(Exception)
+Node *Loop::edSetNode(Node *node)
 {
-  InputPort *ret = 0;
-  if (edCheckAddPort<InputPort, TypeCode*>(inputPortName,_setOfInputPort,type))
+  if(_node==node)
+    return 0;
+  if(node)
     {
-      //InputPort *ret=edAddPort<InputPort, TypeCode*>(inputPortName,_setOfInputPort,type);
-      ret = getRuntime()->createInputPort(inputPortName, _implementation, this, type);
-      _setOfExtraInputPort.insert(ret);
+      if(node->_father)
+        {
+          string what = "Loop::edSetNode: node "; what += node->getName(); what += " is not orphan ! "; 
+          throw Exception(what);
+        }
     }
-      //edAddPort<InputPort,TypeCode*>(inputPortName,_setOfExtraInputPort,type);
+  checkNoCrossHierachyWith(node);
+  StaticDefinedComposedNode::edRemoveChild(_node);
+  Node *ret=_node;
+  _node=node;
+  _node->_father=this;
+  //set _modified flag so that edUpdateState() can refresh state
+  modified();
+  return ret;
 }
 
-void Loop::edRemoveExtraInputPort(InputPort *inputPort)
+bool Loop::edAddChild(Node *node) 
 {
-  edRemovePortTypedFromSet<InputPort>(inputPort,_setOfExtraInputPort);
+  return edSetNode(node);
 }
 
-TypeCode* Loop::MappingDF2DS(TypeCode* type) throw(Exception)
+Node *Loop::edRemoveNode()
 {
-//   switch(type)
-//     {
-//       case Double:
-//     return SDouble;
-//     }
-  string what("Loop::MappingDF2DS : unable to perform DataFlow to DataStream traduction for dataflow type ");
-  //what+=Data::edGetTypeInPrintableForm(type);
-  throw Exception(what);
+  StaticDefinedComposedNode::edRemoveChild(_node);
+  Node *ret=_node;
+  _node=0;
+  modified();
+  return ret;
+}
+
+//! Collect all the child nodes that are ready
+/*!
+ * \param tasks : vector of tasks to collect ready nodes
+ */
+void Loop::getReadyTasks(std::vector<Task *>& tasks)
+{
+  if(!_node)
+    return;
+  /*
+   * To change the way ComposedNode state is handled, uncomment the following line
+   * see Bloc::getReadyTasks
+   */
+  if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED);
+  if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
+    if(_nodeForNullTurnOfLoops)
+      _nodeForNullTurnOfLoops->getReadyTasks(tasks);
+    else
+      {
+        _node->getReadyTasks(tasks);
+        for(set<DSToDFForLoop *>::iterator iter1=_inputsTraducer.begin();iter1!=_inputsTraducer.end();iter1++)
+          (*iter1)->getReadyTasks(tasks);
+        for(set<DFToDSForLoop *>::iterator iter2=_outputsTraducer.begin();iter2!=_outputsTraducer.end();iter2++)
+          (*iter2)->getReadyTasks(tasks);
+      }
+}
+
+void Loop::edRemoveChild(Node *node)
+{
+  StaticDefinedComposedNode::edRemoveChild(node);
+  if(_node==node)
+    _node=0;
+  modified();
+}
+
+std::list<Node *> Loop::edGetDirectDescendants() const
+{
+  list<Node *> ret;
+  if(_node)
+    ret.push_back(_node);
+  return ret;
+}
+
+std::list<InputPort *> Loop::getSetOfInputPort() const
+{
+  list<InputPort *> ret=StaticDefinedComposedNode::getSetOfInputPort();
+  ret.push_back(getDecisionPort());
+  return ret;
+}
+
+int Loop::getNumberOfInputPorts() const
+{
+  return StaticDefinedComposedNode::getNumberOfInputPorts()+1;
+}
+
+int Loop::getMaxLevelOfParallelism() const
+{
+  if(!_node)
+    return 0;
+  return _node->getMaxLevelOfParallelism();
 }
 
-TypeCode* Loop::MappingDS2DF(TypeCode* type) throw(Exception)
+void Loop::getWeightRegardingDPL(ComplexWeight *weight)
 {
-//   switch(type)
-//     {
-//       case SDouble:
-//     return Double;
-//     }
-  string what("Loop::MappingDS2DF : unable to perform DataStream to DataFlow traduction for datastream type ");
-  //what+=TypeCheckerDataStream::edGetTypeInPrintableForm(type);
+  if(_node)
+    _node->getWeightRegardingDPL(weight);
+}
+
+void Loop::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
+{
+  if(_node)
+    _node->partitionRegardingDPL(pd,zeMap);
+}
+
+Node *Loop::getChildByShortName(const std::string& name) const
+{
+  if (_node)
+    if(name==_node->getName())
+      return _node;
+  string what("node "); what+= name ; what+=" is not a child of loop node "; what += getName();
   throw Exception(what);
 }
 
-InPort *Loop::buildDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfView)
+TypeCode* Loop::MappingDF2DS(TypeCode* type)
+{
+  return type;
+}
+
+TypeCode* Loop::MappingDS2DF(TypeCode* type)
+{
+  return type;
+}
+
+void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
 {
   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=InputPort::NAME)
-    return port;
-  else
-    if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
-      return port;
+  if(typeOfPortInstance!=InputPort::NAME ||
+     (typeOfPortInstance == InputPort::NAME && 
+      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME && 
+      !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
+    return ;
   InputPort *portCasted=(InputPort *)port;
   set<DSToDFForLoop*>::iterator iter;
   //Determinig if a DSToDFForLoop node has already been created for delegation of 'port'
@@ -140,52 +472,55 @@ InPort *Loop::buildDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfV
       break;
   if(iter==_inputsTraducer.end())
     {//first time that 'port' is delegated on higher level
-      _inputsTraducer.insert(new DSToDFForLoop(this,portCasted->getName(),Loop::MappingDF2DS(portCasted->edGetType())));
-      iter=_inputsTraducer.end(); iter--;
-      (*iter)->getOutputPort("")->edAddInputPort(portCasted);
-      //WARNING control flow has to be added
-      (*iter)->getOutGate()->edAddInGate(portCasted->getNode()->getInGate());//WARNING HERE MAYBE HAS TO BE IMPROVED - SEPARATE COUNTERS
+      pair<set<DSToDFForLoop*>::iterator, bool> iter2=_inputsTraducer.insert(new DSToDFForLoop(this,portCasted->getName(),Loop::MappingDF2DS(portCasted->edGetType())));
+      iter=iter2.first;
+      (*iter)->getOutputPort("")->addInPort(portCasted);
     }
   else
     (*iter)->loopHasOneMoreRef();
-  return (*iter)->getInputDataStreamPort("");
+  port=(*iter)->getInputDataStreamPort("");
 }
 
-OutPort *Loop::buildDelegateOf(OutPort *port, const set<ComposedNode *>& pointsOfView)
+void Loop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
 {
-  string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=OutputPort::NAME)
-    return port;
-  else
-    if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
-      return port;
-  OutputPort *portCasted=(OutputPort *)port;
+  string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
+  if(typeOfPortInstance!=OutputPort::NAME ||
+    ( typeOfPortInstance == OutputPort::NAME && 
+      finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME && 
+      !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
+    return ;
+  OutPort *portCasted=port.first;
   set<DFToDSForLoop*>::iterator iter;
   //Determinig if a DFToDSForLoop node has already been created for delegation of 'port'
   for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
-    if(portCasted->isAlreadyInSet((*iter)->getInputPort("")))
+    if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
       break;
+  DFToDSForLoop *kl;
   if(iter==_outputsTraducer.end())
     {//first time that 'port' is delegated on higher level
-      _outputsTraducer.insert(new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType()));
-      iter=_outputsTraducer.end(); iter--;
-      portCasted->edAddInputPort((*iter)->getInputPort(""));
-      //WARNING control flow has to be added
-      portCasted->getNode()->getOutGate()->edAddInGate((*iter)->getInGate());//WARNING HERE MAYBE HAS TO BE IMPROVED - SEPARATE COUNTERS
+      //_outputsTraducer.insert(new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType()));
+      kl=new DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType());
+      pair<set<DFToDSForLoop*>::iterator, bool> iter2=_outputsTraducer.insert(kl);
+      iter=iter2.first;
+      portCasted->addInPort((*iter)->getInputPort(""));
     }
   else
-    (*iter)->loopHasOneMoreRef();
-  return (*iter)->getOutputDataStreamPort("");
+    {
+      kl=*iter;
+      kl->loopHasOneMoreRef();
+    }
+  edAddLink(isInMyDescendance((port.first)->getNode())->getOutGate(),kl->getInGate());
+  port.first=(*iter)->getOutputDataStreamPort("");
 }
 
-InPort *Loop::getDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)
+void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
 {
   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=InputPort::NAME)
-    return port;
-  else
-    if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
-      return port;
+  if(typeOfPortInstance!=InputPort::NAME ||
+     (typeOfPortInstance == InputPort::NAME && 
+      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME && 
+      !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
+    return ;
   InputPort *portCasted=(InputPort *)port;
   set<DSToDFForLoop*>::iterator iter;
   for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
@@ -193,43 +528,44 @@ InPort *Loop::getDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfVie
       break;
   if(iter==_inputsTraducer.end())
     {
-      string what("Loop::getDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
+      string what("Loop::getDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
       throw Exception(what);
     }
   else
-    return (*iter)->getInputDataStreamPort("");
+    port=(*iter)->getInputDataStreamPort("");
 }
 
-OutPort *Loop::getDelegateOf(OutPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)
+void Loop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, 
+                         const std::list<ComposedNode *>& pointsOfView)
 {
-  string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=OutputPort::NAME)
-    return port;
-  else
-    if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
-      return port;
-  OutputPort *portCasted=(OutputPort *)port;
+  string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
+  if(typeOfPortInstance!=OutputPort::NAME ||
+    ( typeOfPortInstance == OutputPort::NAME && 
+      finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME && 
+      !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
+    return ;
+  OutPort *portCasted=port.first;
   set<DFToDSForLoop*>::iterator iter;
   for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
-    if(portCasted->isAlreadyInSet((*iter)->getInputPort("")))
+    if(portCasted->isAlreadyLinkedWith((*iter)->getInputPort("")))
       break;
   if(iter==_outputsTraducer.end())
     {
-      string what("Loop::getDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
+      string what("Loop::getDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
       throw Exception(what);
     }
   else
-    return (*iter)->getOutputDataStreamPort("");
+    port.first=(*iter)->getOutputDataStreamPort("");
 }
 
-InPort *Loop::releaseDelegateOf(InPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)
+void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
 {
   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=InputPort::NAME)
-    return port;
-  else
-    if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
-      return port;
+  if(typeOfPortInstance!=InputPort::NAME ||
+    ( typeOfPortInstance == InputPort::NAME && 
+      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME && 
+      !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
+    return ;
   InputPort *portCasted=(InputPort *)port;
   set<DSToDFForLoop*>::iterator iter;
   for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
@@ -242,55 +578,131 @@ InPort *Loop::releaseDelegateOf(InPort *port, const set<ComposedNode *>& pointsO
     }
   else
     {
-      InPort *ret=(*iter)->getInputDataStreamPort("");
+      port=(*iter)->getInputDataStreamPort("");
       if((*iter)->loopHasOneLessRef())
-       _inputsTraducer.erase(iter);
-      return ret;
+        {
+          (*iter)->getOutputPort("")->removeInPort(portCasted,false);
+          delete (*iter);
+          _inputsTraducer.erase(iter);
+        }
     }
 }
 
-OutPort *Loop::releaseDelegateOf(OutPort *port, const set<ComposedNode *>& pointsOfView) throw(Exception)
+void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
 {
-    string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=OutputPort::NAME)
-    return port;
-  else
-    if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
-      return port;
-  OutputPort *portCasted=(OutputPort *)port;
+  if(portDwn==portUp)
+    return ;
   set<DFToDSForLoop*>::iterator iter;
   for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
-    if(portCasted->isAlreadyInSet((*iter)->getInputPort("")))
+    if((*iter)->getOutputDataStreamPort("")==portUp)
       break;
-  if(iter==_outputsTraducer.end())
+  if((*iter)->loopHasOneLessRef())
     {
-      string what("Loop::releaseDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name; 
-      throw Exception(what);
-    }
-  else
-    {
-      OutPort *ret=(*iter)->getOutputDataStreamPort("");
-      if((*iter)->loopHasOneLessRef())
-       _outputsTraducer.erase(iter);
-      return ret;
+      portDwn->removeInPort((*iter)->getInputPort(""),false);
+      delete (*iter);
+      _outputsTraducer.erase(iter);
     }
 }
 
-void Loop::checkNoCyclePassingThrough(Node *node) throw(Exception)
+void Loop::checkNoCyclePassingThrough(Node *node)
 {
-  throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured");
+  //throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured");
 }
 
-/**
- * @note : States if a DF port must be considered on an upper level in hierarchy as a DS port or not from 'pointsOfView' observers.
- * @return : 
+void Loop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
+{
+  Node *nodeEnd=end->getNode();
+  if(nodeEnd==this)
+    {//In this case 'end' port is a special port of this (for exemple ForLoop::_nbOfTimesPort)
+      //ASSERT(!direction) see Loop::checkControlDependancy (bw only)
+      solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
+    }
+  else
+    StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info);
+}
+
+/*!
+ * \note : States if a DF port must be considered on an upper level in hierarchy as a DS port or not from 'pointsOfView' observers.
+ * \return : 
  *            - True : a traduction DF->DS has to be done
  *            - False : no traduction needed
  */
-bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const set<ComposedNode *>& pointsOfView)
+bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::list<ComposedNode *>& pointsOfView)
 {
   bool ret=false;
-  for(set<ComposedNode *>::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++)
+  for(list<ComposedNode *>::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++)
     ret=(*iter)->isRepeatedUnpredictablySeveralTimes();
   return ret;
 }
+
+//! Connect an OutPort to an InPort and add control link if necessary
+/*!
+ * Connect the ports with a data link (edAddLink) 
+ * In a Loop don't add control flow link : use this only to add data back links
+ *
+ * \param start : the OutPort to connect
+ * \param end : the InPort to connect
+ * \return  true if a new link has been created, false otherwise.
+ */
+bool Loop::edAddDFLink(OutPort *start, InPort *end)
+{
+  return edAddLink(start,end);
+}
+
+//! Dump the node state to a stream
+/*!
+ * \param os : the output stream
+ */
+void Loop::writeDot(std::ostream &os) const
+{
+  os << "  subgraph cluster_" << getId() << "  {\n" ;
+  //only one node in a loop
+  if(_node)
+    {
+      _node->writeDot(os);
+      os << getId() << " -> " << _node->getId() << ";\n";
+    }
+  os << "}\n" ;
+  os << getId() << "[fillcolor=\"" ;
+  YACS::StatesForNode state=getEffectiveState();
+  os << getColorState(state);
+  os << "\" label=\"" << "Loop:" ;
+  os << getQualifiedName() <<"\"];\n";
+}
+
+
+void Loop::accept(Visitor *visitor)
+{
+  visitor->visitLoop(this);
+}
+
+void Loop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
+                                  std::map < ComposedNode *,  std::list < OutPort * >, SortHierarc >& fw,
+                                  std::vector<OutPort *>& fwCross,
+                                  std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
+                                  LinkInfo& info) const
+{
+  //First testing if end==getDecisionPort. This is the only case possible in theory.
+  if(end!=getDecisionPort())
+    return StaticDefinedComposedNode::checkControlDependancy(start,end,cross,fw,fwCross,bw,info);
+  if(cross)
+    throw Exception("Internal error occured - cross type link detected on decision port of a loop. Forbidden !");
+  fw[(ComposedNode *)this].push_back(start);
+}
+
+void Loop::checkBasicConsistency() const
+{
+  DEBTRACE("Loop::checkBasicConsistency");
+  ComposedNode::checkBasicConsistency();
+  if(!_node)
+    throw Exception("For a loop, internal node is mandatory");
+}
+
+/*!
+ *  For use only when loading a previously saved execution
+ */
+
+void YACS::ENGINE::NbDoneLoader(Loop* node, int val)
+{
+  node->_nbOfTurns = val;
+}