Salome HOME
PR: merge from BR_DATACONV_PR tag "mergeto_trunk_25oct06"
[modules/yacs.git] / src / engine / Bloc.cxx
index e02d45950c04e6b0d2cb5c5e9a07c56a5a157944..b25477be87b7ec57be75dae04ce00d211ce4d20b 100644 (file)
@@ -2,20 +2,22 @@
 #include "ElementaryNode.hxx"
 
 using namespace YACS::ENGINE;
+using namespace std;
 
-Bloc::Bloc(const std::string& name):ComposedNode(name)
+Bloc::Bloc(const string& name):ComposedNode(name)
 {
 }
 
 Bloc::~Bloc()
 {
-  for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     delete *iter;
 }
 
 void Bloc::init()
 {
-  for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  _inGate.exReset();
+  for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     (*iter)->init();
   if(_inGate.exIsReady())
     _state=YACS::TOACTIVATE;
@@ -31,54 +33,62 @@ bool Bloc::isFinished()
 int Bloc::getNumberOfCFLinks() const
 {
   int ret=0;
-  for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     {
       ret+=(*iter)->getOutGate()->getNbOfInGatesConnected();
     }
   return ret;
 }
 
-std::vector<Task *> Bloc::getNextTasks(bool& isMore)
+vector<Task *> Bloc::getNextTasks(bool& isMore)
 {
-  std::vector<Task *> ret;
+  vector<Task *> ret;
   isMore=false;
   if(_state==YACS::DONE || _state==YACS::INITED)
     return ret;
-  for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     (*iter)->getReadyTasks(ret);
   isMore=!ret.empty();
   return ret;
 }
 
-void Bloc::getReadyTasks(std::vector<Task *>& tasks)
+void Bloc::getReadyTasks(vector<Task *>& tasks)
 {
   if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
-    for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+    for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
       (*iter)->getReadyTasks(tasks);
 }
 
-std::list<ElementaryNode *> Bloc::getRecursiveConstituents()
+set<ElementaryNode *> Bloc::getRecursiveConstituents()
 {
-  std::list<ElementaryNode *> ret;
-  for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  set<ElementaryNode *> ret;
+  for(set<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     {
-      std::list<ElementaryNode *> myCurrentList=(*iter)->getRecursiveConstituents();
-      ret.insert(ret.begin(),myCurrentList.begin(),myCurrentList.end());
+      set<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
+      ret.insert(myCurrentSet.begin(),myCurrentSet.end());
     }
   return ret;
 }
 
 /**
- * @ note : Update the '_state' attribute.
- *          Typically called by 'this->_inGate' when 'this->_inGate' is ready. Contrary to Node::exUpdateState no check done on inputs
- *          because internal linked DF inputports are not valid yet.
+ * Update the '_state' attribute.
+ * Typically called by 'this->_inGate' when 'this->_inGate' is ready. Contrary to Node::exUpdateState no check done on inputs
+ * because internal linked DF inputports are not valid yet.
  */
+
 void Bloc::exUpdateState()
 {
   if(_inGate.exIsReady())
     _state=YACS::TOACTIVATE;
 }
 
+/**
+* If node is already a direct child of current bloc, do nothing.
+* If node is a child of another bloc, throw exception.
+* If node name already used in bloc, throw exception.
+* Publish inputPorts in current bloc and ancestors.
+*/
+
 bool Bloc::edAddChild(Node *node) throw(Exception)
 {
   if(isNodeAlreadyAggregated(node))
@@ -88,26 +98,41 @@ bool Bloc::edAddChild(Node *node) throw(Exception)
       else
        throw Exception("Bloc::edAddChild : Internal error occured");
     }
+
   if(node->_father)
-    throw Exception("Bloc::edAddChild : node is not orphan");
+    {
+      string what = "Bloc::edAddChild: node is not orphan: "; what += node->getName();
+      throw Exception(what);
+    }
+
   if(isNameAlreadyUsed(node->getName()))
     {
-      std::string what("Bloc::edAddChild : name "); what+=node->getName(); what+=" already exists in the scope of "; what+=_name;
+      string what("Bloc::edAddChild : name "); what+=node->getName(); what+=" already exists in the scope of "; what+=_name;
       throw Exception(what);
     }
+
   node->_father=this;
-  _listOfNode.push_back(node);
+  _setOfNode.insert(node);
+
+  ComposedNode *iter=node->_father;
+  while(iter)
+    {
+      for(set<InputPort *>::iterator itn = node->_setOfInputPort.begin(); itn != node->_setOfInputPort.end(); itn++)
+       iter->publishInputPort(*itn);
+      iter=iter->_father;
+    }
+
   return true;
 }
 
 /**
- * @ note : Remove 'node' from the list of direct children.
- *          WARNING 1 : node is destroyed after invocation of this method because Bloc class has ownership of its child nodes.
- *          WARNING 2 : all links to 'node' are automatically desactivated. As consequence this method is quite heavy for big graphs due to
- *                      unilateral storing policy of links. 
- * @ exception : If 'node' is NOT the direct son of 'this'.
- *
+ * Remove 'node' from the set of direct children.
+ * WARNING 1 : node is destroyed after invocation of this method because Bloc class has ownership of its child nodes.
+ * WARNING 2 : all links to 'node' are automatically desactivated. As consequence this method is quite heavy for big graphs due to
+ *             unilateral storing policy of links. 
+ * @exception If 'node' is NOT the direct son of 'this'.
  */
+
 void Bloc::edRemoveChild(Node *node) throw(Exception)
 {
   if(node->_father!=this)
@@ -116,18 +141,18 @@ void Bloc::edRemoveChild(Node *node) throw(Exception)
     throw Exception("Bloc::edRemoveChild : Internal error occured");
   ComposedNode *myRootNode=getRootNode();
   myRootNode->disconnectAllLinksConnectedTo(node);
-  _listOfNode.remove(node);
+  _setOfNode.erase(node);
   delete node;
 }
 
-void Bloc::selectRunnableTasks(std::vector<Task *>& tasks)
+void Bloc::selectRunnableTasks(vector<Task *>& tasks)
 {
 }
 
 bool Bloc::areAllSubNodesFinished() const
 {
   bool ret=true;
-  for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end() && ret;iter++)
+  for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end() && ret;iter++)
     if((*iter)->_state!=YACS::DONE)
       ret=false;
   return ret;
@@ -135,7 +160,7 @@ bool Bloc::areAllSubNodesFinished() const
 
 bool Bloc::isNodeAlreadyAggregated(Node *node) const
 {
-  for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     {
       if((*iter)==node)
        return true;
@@ -143,52 +168,49 @@ bool Bloc::isNodeAlreadyAggregated(Node *node) const
   return false;
 }
 
-bool Bloc::isNameAlreadyUsed(const std::string& name) const
+bool Bloc::isNameAlreadyUsed(const string& name) const
 {
-  for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
       if((*iter)->getName()==name)
        return true;
   return false;
 }
 
+bool insertNodeChildrenInSet(Node *node, set<Node *> nodeSet)
+{
+  bool verdict=true;
+  set<Node *> outNodes=node->getOutNodes();
+  for (set<Node *>::iterator iter=outNodes.begin();iter!=outNodes.end(); iter++)
+    {
+      verdict=(nodeSet.insert(*iter)).second;
+      if (verdict) verdict = insertNodeChildrenInSet((*iter),nodeSet);
+      if (!verdict) break;
+    }
+  return verdict;
+}
+
 /**
- * @ note : Checks that in the forest from 'node' there are NO back-edges.
+ * @note : Checks that in the forest from 'node' there are NO back-edges.
  *          WARNING : When using this method 'node' has to be checked in order to be part of direct children of 'this'. 
  *
  */
 void Bloc::checkNoCyclePassingThrough(Node *node) throw(Exception)
 {
-  initChildrenForDFS();
-  node->_colour=YACS::Grey;
-  bool verdict=true;
-  std::list<Node *> currentNodesToTest;
-  currentNodesToTest.push_back(node);
-  for(std::list<Node *>::iterator iter1=currentNodesToTest.begin();iter1!=currentNodesToTest.end() && verdict;)
-    {
-      std::list<Node *> outNodes=(*iter1)->getOutNodes();
-      for(std::list<Node *>::iterator iter2=outNodes.begin();iter2!=outNodes.end() && verdict;iter2++)
-       if((*iter2)->_colour==YACS::White)
-         {
-           currentNodesToTest.push_back(*iter2);
-           (*iter2)->_colour=YACS::Grey;
-         }
-       else
-         verdict=false;
-      iter1=currentNodesToTest.erase(iter1);
-    }
-  if(!verdict)
+  set<Node *> currentNodesToTest;
+  currentNodesToTest.insert(node);
+  if (!insertNodeChildrenInSet(node,currentNodesToTest))
     throw Exception("Cycle has been detected");
 }
 
 void Bloc::initChildrenForDFS() const
 {
-  for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+  for(set<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     (*iter)->initForDFS();
 }
 
 /**
  *
- * @ note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
+ * @note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
  *          'when event == START'.
  *          WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by ComposedNode::notifyFrom)
  *
@@ -201,7 +223,7 @@ YACS::Event Bloc::updateStateOnStartEventFrom(Node *node)
 
 /**
  *
- * @ note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
+ * @note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
  *          'when event == FINISH'.
  *          WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by ComposedNode::notifyFrom)
  *