Salome HOME
updated copyright message
[modules/yacs.git] / src / engine / Loop.cxx
index 344a59c4bf63bdb0e7e218fdbb4fa1ced681a4f0..f41ac414b378fcbb957d3a78b4b643f79a816032 100644 (file)
@@ -1,13 +1,36 @@
+// Copyright (C) 2006-2023  CEA, EDF
+//
+// 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>
 
+//#define _DEVDEBUG_
+#include "YacsTrace.hxx"
+
 using namespace YACS::ENGINE;
 using namespace std;
 
@@ -24,7 +47,7 @@ void InputPort4DF2DS::getAllRepresentants(std::set<InPort *>& repr) const
   repr.insert(s.begin(),s.end());
 }
 
-void *InputPort4DF2DS::get() const throw(Exception)
+void *InputPort4DF2DS::get() const
 {
   if(!_data)
     {
@@ -52,7 +75,7 @@ void InputPort4DF2DS::exSaveInit()
   _initValue->incrRef();
 }
 
-void InputPort4DF2DS::put(const void *data) throw(ConversionException)
+void InputPort4DF2DS::put(const void *data)
 {
   put((Any *)data);
 }
@@ -62,10 +85,16 @@ InputPort *InputPort4DF2DS::clone(Node *newHelder) const
   throw Exception("InputPort4DF2DS::clone : internal error");
 }
 
-void InputPort4DF2DS::put(Any *data)
+void InputPort4DF2DS::releaseData()
 {
   if(_data)
     _data->decrRef();
+  _data = nullptr;
+}
+
+void InputPort4DF2DS::put(Any *data)
+{
+  InputPort4DF2DS::releaseData();
   _data=data;
   _data->incrRef();
 }
@@ -86,19 +115,25 @@ DFToDSForLoop::DFToDSForLoop(Loop *loop, const std::string& name, TypeCode* type
 
 DFToDSForLoop::~DFToDSForLoop()
 {
+  edDisconnectAllLinksWithMe();
 }
 
 void DFToDSForLoop::getReadyTasks(std::vector<Task *>& tasks)
 {
 }
 
-InputPort *DFToDSForLoop::getInputPort(const std::string& name) const throw(Exception)
+InputPort *DFToDSForLoop::getInputPort(const std::string& name) const
 {
+  try {
+    return Node::getInputPort(name);
+  }
+  catch(Exception& e) {}
+
   list<InputPort *>::const_iterator it =_setOfInputPort.begin();
   return (*it);
 }
 
-OutputDataStreamPort *DFToDSForLoop::getOutputDataStreamPort(const std::string& name) const throw(Exception)
+OutputDataStreamPort *DFToDSForLoop::getOutputDataStreamPort(const std::string& name) const
 {
   list<OutputDataStreamPort *>::const_iterator it =_setOfOutputDataStreamPort.begin();
   return (*it);
@@ -132,7 +167,7 @@ void OutputPort4DS2DF::getAllRepresented(std::set<OutPort *>& represented) const
     (*iter)->getAllRepresented(represented);
 }
 
-void OutputPort4DS2DF::put(const void *data) throw(ConversionException)
+void OutputPort4DS2DF::put(const void *data)
 {
   put((Any *)data);
   OutputPort::put(data);
@@ -185,19 +220,20 @@ Node *DSToDFForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
 
 DSToDFForLoop::~DSToDFForLoop()
 {
+  edDisconnectAllLinksWithMe();
 }
 
 void DSToDFForLoop::getReadyTasks(std::vector<Task *>& tasks)
 {
 }
 
-OutputPort *DSToDFForLoop::getOutputPort(const std::string& name) const throw(Exception)
+OutputPort *DSToDFForLoop::getOutputPort(const std::string& name) const
 {
   list<OutputPort *>::const_iterator it = _setOfOutputPort.begin();
   return (*it);
 }
 
-InputDataStreamPort *DSToDFForLoop::getInputDataStreamPort(const std::string& name) const throw(Exception)
+InputDataStreamPort *DSToDFForLoop::getInputDataStreamPort(const std::string& name) const
 {
   list<InputDataStreamPort *>::const_iterator it = _setOfInputDataStreamPort.begin();
   return (*it);
@@ -234,17 +270,11 @@ Node *FakeNodeForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
 void FakeNodeForLoop::exForwardFailed()
 {
   _loop->exForwardFailed();
-  FakeNodeForLoop *normallyThis=_loop->_nodeForNullTurnOfLoops;
-  _loop->_nodeForNullTurnOfLoops=0;
-  delete normallyThis;
 }
 
 void FakeNodeForLoop::exForwardFinished()
 { 
   _loop->exForwardFinished();
-  FakeNodeForLoop *normallyThis=_loop->_nodeForNullTurnOfLoops;
-  _loop->_nodeForNullTurnOfLoops=0;
-  delete normallyThis;
 }
 
 void FakeNodeForLoop::execute()
@@ -266,7 +296,7 @@ void FakeNodeForLoop::finished()
   _loop->setState(YACS::DONE);
 }
 
-Loop::Loop(const Loop& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_nbOfTurns(0),_nodeForNullTurnOfLoops(0)
+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);
@@ -279,7 +309,7 @@ Loop::Loop(const std::string& name):StaticDefinedComposedNode(name),_node(0),_nb
 Loop::~Loop()
 {
   delete _node;
-  delete _nodeForNullTurnOfLoops;
+  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++)
@@ -310,18 +340,27 @@ Node *Loop::edSetNode(Node *node)
           throw Exception(what);
         }
     }
+  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;
 }
 
+bool Loop::edAddChild(Node *node) 
+{
+  return edSetNode(node);
+}
+
 Node *Loop::edRemoveNode()
 {
   StaticDefinedComposedNode::edRemoveChild(_node);
   Node *ret=_node;
   _node=0;
+  modified();
   return ret;
 }
 
@@ -351,53 +390,78 @@ void Loop::getReadyTasks(std::vector<Task *>& tasks)
       }
 }
 
-void Loop::edRemoveChild(Node *node) throw(Exception)
+void Loop::edRemoveChild(Node *node)
 {
   StaticDefinedComposedNode::edRemoveChild(node);
   if(_node==node)
     _node=0;
+  modified();
 }
 
-void Loop::selectRunnableTasks(std::vector<Task *>& tasks)
+std::list<Node *> Loop::edGetDirectDescendants() const
 {
+  list<Node *> ret;
+  if(_node)
+    ret.push_back(_node);
+  return ret;
 }
 
-std::set<Node *> Loop::edGetDirectDescendants() const
+std::list<InputPort *> Loop::getSetOfInputPort() const
 {
-  set<Node *> ret;
-  if(_node)
-    ret.insert(_node);
+  list<InputPort *> ret=StaticDefinedComposedNode::getSetOfInputPort();
+  ret.push_back(getDecisionPort());
   return ret;
 }
 
-void Loop::checkConsistency(ComposedNode *pointOfView) const throw(Exception)
+int Loop::getNumberOfInputPorts() const
 {
+  return StaticDefinedComposedNode::getNumberOfInputPorts()+1;
 }
 
-Node *Loop::getChildByShortName(const std::string& name) const throw(Exception)
+int Loop::getMaxLevelOfParallelism() const
 {
-  if(name==_node->getName())
-    return _node;
+  if(!_node)
+    return 0;
+  return _node->getMaxLevelOfParallelism();
+}
+
+void Loop::getWeightRegardingDPL(ComplexWeight *weight)
+{
+  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);
 }
 
-TypeCode* Loop::MappingDF2DS(TypeCode* type) throw(Exception)
+TypeCode* Loop::MappingDF2DS(TypeCode* type)
 {
   return type;
 }
 
-TypeCode* Loop::MappingDS2DF(TypeCode* type) throw(Exception)
+TypeCode* Loop::MappingDS2DF(TypeCode* type)
 {
   return type;
 }
 
-void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set<ComposedNode *>& pointsOfView)
+void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
 {
   string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=InputPort::NAME or
-     (typeOfPortInstance == InputPort::NAME and 
-      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME and 
+  if(typeOfPortInstance!=InputPort::NAME ||
+     (typeOfPortInstance == InputPort::NAME && 
+      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME && 
       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
     return ;
   InputPort *portCasted=(InputPort *)port;
@@ -417,12 +481,12 @@ void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::se
   port=(*iter)->getInputDataStreamPort("");
 }
 
-void Loop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::set<ComposedNode *>& pointsOfView)
+void Loop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
 {
   string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=OutputPort::NAME or
-    ( typeOfPortInstance == OutputPort::NAME and 
-      finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME and 
+  if(typeOfPortInstance!=OutputPort::NAME ||
+    ( typeOfPortInstance == OutputPort::NAME && 
+      finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME && 
       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
     return ;
   OutPort *portCasted=port.first;
@@ -449,12 +513,12 @@ void Loop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalT
   port.first=(*iter)->getOutputDataStreamPort("");
 }
 
-void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::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 or
-     (typeOfPortInstance == InputPort::NAME and 
-      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME and 
+  if(typeOfPortInstance!=InputPort::NAME ||
+     (typeOfPortInstance == InputPort::NAME && 
+      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME && 
       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
     return ;
   InputPort *portCasted=(InputPort *)port;
@@ -472,12 +536,12 @@ void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::set<
 }
 
 void Loop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, 
-                         const std::set<ComposedNode *>& pointsOfView) throw(Exception)
+                         const std::list<ComposedNode *>& pointsOfView)
 {
   string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
-  if(typeOfPortInstance!=OutputPort::NAME or
-    ( typeOfPortInstance == OutputPort::NAME and 
-      finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME and 
+  if(typeOfPortInstance!=OutputPort::NAME ||
+    ( typeOfPortInstance == OutputPort::NAME && 
+      finalTarget->getNameOfTypeOfCurrentInstance()== InputPort::NAME && 
       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
     return ;
   OutPort *portCasted=port.first;
@@ -494,12 +558,12 @@ void Loop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTar
     port.first=(*iter)->getOutputDataStreamPort("");
 }
 
-void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::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 or
-    ( typeOfPortInstance == InputPort::NAME and 
-      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME and 
+  if(typeOfPortInstance!=InputPort::NAME ||
+    ( typeOfPortInstance == InputPort::NAME && 
+      initialStart->getNameOfTypeOfCurrentInstance()== OutputPort::NAME && 
       !isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView)) )
     return ;
   InputPort *portCasted=(InputPort *)port;
@@ -524,7 +588,7 @@ void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::
     }
 }
 
-void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set<ComposedNode *>& pointsOfView) throw(Exception)
+void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
 {
   if(portDwn==portUp)
     return ;
@@ -540,21 +604,33 @@ void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTar
     }
 }
 
-void Loop::checkNoCyclePassingThrough(Node *node) throw(Exception)
+void Loop::checkNoCyclePassingThrough(Node *node)
 {
   //throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured");
 }
 
+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 std::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;
 }
@@ -568,7 +644,7 @@ bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::set<ComposedNode *
  * \param end : the InPort to connect
  * \return  true if a new link has been created, false otherwise.
  */
-bool Loop::edAddDFLink(OutPort *start, InPort *end) throw(Exception)
+bool Loop::edAddDFLink(OutPort *start, InPort *end)
 {
   return edAddLink(start,end);
 }
@@ -577,12 +653,15 @@ bool Loop::edAddDFLink(OutPort *start, InPort *end) throw(Exception)
 /*!
  * \param os : the output stream
  */
-void Loop::writeDot(std::ostream &os)
+void Loop::writeDot(std::ostream &os) const
 {
   os << "  subgraph cluster_" << getId() << "  {\n" ;
   //only one node in a loop
-  _node->writeDot(os);
-  os << getId() << " -> " << _node->getId() << ";\n";
+  if(_node)
+    {
+      _node->writeDot(os);
+      os << getId() << " -> " << _node->getId() << ";\n";
+    }
   os << "}\n" ;
   os << getId() << "[fillcolor=\"" ;
   YACS::StatesForNode state=getEffectiveState();
@@ -597,6 +676,28 @@ 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
  */