Salome HOME
Bug fix: don't set "Loading" state for MacroNodes in InitialState() function (called...
[modules/superv.git] / src / GraphExecutor / DataFlowExecutor_InNode.cxx
index 76ff07ffee78b77753ffb28d0dcda505f4ce1c35..e03187981ecf14869adaff2be373016473aad782 100644 (file)
@@ -32,6 +32,7 @@ using namespace std;
 #include <iostream>
 #include <unistd.h>
 #include <stdio.h>
+#include <errno.h>
 
 #include "OpUtil.hxx"
 
@@ -47,11 +48,12 @@ using namespace std;
 #include "DataFlowBase_SwitchNode.hxx"
 #include "DataFlowBase_EndOfSwitchNode.hxx"
 
-#include "DataFlowExecutor_OutNode.hxx"
+#include "DataFlowExecutor_DataFlow.hxx"
+#include "DataFlowEditor_DataFlow.hxx"   // GraphEditor package must be built BEFORE
 
 static void InitInNode( int &_RewindStack ,
                         SUPERV::ControlState &_ControlState ,
-                        SUPERV::AutomatonState &_currentState ,
+                        GraphExecutor::AutomatonState &_currentState ,
                         GraphExecutor::InNode ** _aReStartNode ,
                         bool & _PyFuncRunned ,
                         PyObject ** _MyPyRunMethod ,
@@ -74,10 +76,11 @@ static void InitInNode( int &_RewindStack ,
                         GraphExecutor::FiniteStateMachine ** _Automaton ,
                         GraphExecutor::FiniteStateMachine * theAutomaton ,
                         CORBA::ORB_ptr * _Orb ,
-                        CORBA::ORB_ptr ORB ) {
+                        CORBA::ORB_ptr ORB,
+                       bool &_Loading ) {
   _RewindStack = 0 ;
   _ControlState = SUPERV::VoidState ;
-  _currentState = SUPERV::UnKnownState ;
+  _currentState = GraphExecutor::UnKnownState ;
   *_aReStartNode = NULL ;
   _PyFuncRunned = false ;
   *_MyPyRunMethod = NULL ;
@@ -126,6 +129,7 @@ static void InitInNode( int &_RewindStack ,
   }
   *_Automaton = theAutomaton ;
   *_Orb = CORBA::ORB::_nil();
+  _Loading = false;
 }
 
 GraphExecutor::FiniteStateMachine * theAutomaton = new GraphExecutor::FiniteStateMachine() ;
@@ -158,7 +162,8 @@ GraphExecutor::InNode::InNode() {
               &_Automaton ,
               theAutomaton ,
               &_Orb ,
-              CORBA::ORB::_nil() ) ;
+              CORBA::ORB::_nil(),
+             _Loading ) ;
 }
 
 GraphExecutor::InNode::InNode( CORBA::ORB_ptr ORB,
@@ -215,7 +220,8 @@ GraphExecutor::InNode::InNode( CORBA::ORB_ptr ORB,
               &_Automaton ,
               theAutomaton ,
               &_Orb ,
-              ORB ) ;
+              ORB,
+             _Loading ) ;
   SetDebug( ORB , Graph_prof_debug , Graph_fdebug ) ;
 
   _ComputingNode = NULL ;
@@ -267,6 +273,22 @@ GraphExecutor::InNode::InNode( CORBA::ORB_ptr ORB,
     _ComputingNode = (GraphBase::ComputingNode *) _InLineNode ;
     break ;
   }
+  case SUPERV::MacroNode : {
+    cdebug << "GraphExecutor::InNode::InNode SUPERV::MacroNode : " << NodeName << endl ;
+    _GraphMacroNode = new GraphBase::Graph( ORB , ptrNamingService ,
+//                                            aFuncName[0].c_str() , *aPythonFunction[0] ,
+                                            NodeName , akind ,
+//                                            NodeFirstCreation , NodeLastModification  ,
+//                                            NodeEditorRelease , NodeAuthor ,
+//                                            NodeComment , GeneratedName ,
+//                                            NodeX , NodeY ,
+                                            Graph_prof_debug , Graph_fdebug ) ;
+    _ComputingNode = (GraphBase::ComputingNode *) _GraphMacroNode ;
+    _InLineNode = (GraphBase::InLineNode *) _ComputingNode ;
+    _GOTONode = (GraphBase::GOTONode *) _InLineNode ;
+    _GraphMacroNode->Coordinates( NodeX , NodeY ) ;
+    break ;
+  }
   case SUPERV::GOTONode : {
     cdebug << "GraphEditor::InNode::InNode SUPERV::GOTONode : " << NodeName ;
     _GOTONode = new GraphBase::GOTONode( ORB , ptrNamingService ,
@@ -410,14 +432,14 @@ bool GraphExecutor::InNode::Ping() {
   if ( IsFactoryNode() ) {
     RetVal = !CORBA::is_nil( _FactoryNode->Component() ) ;
     if ( RetVal ) {
-      if ( State() != SUPERV::SuspendedExecutingState ) {
+      if ( State() != GraphExecutor::SuspendedExecutingState ) {
         try {
           _FactoryNode->Component()->ping() ;
        }
         catch( ... ) {
-          cdebug << "InNode::Ping() catched" << endl ;
-          State( SUPERV::ErroredState ) ;
-          _OutNode->State( SUPERV::ErroredState ) ;
+          cdebug << "InNode::Ping() ERROR catched" << endl ;
+          State( GraphExecutor::ErroredState ) ;
+          _OutNode->State( GraphExecutor::ErroredState ) ;
           RetVal = false ;
        }
       }
@@ -442,14 +464,16 @@ void GraphExecutor::InNode::ExitThread() {
 
 bool GraphExecutor::InNode::Suspend() {
   cdebug_in << "GraphExecutor::InNode::Suspend " << Name() << " " << ThreadNo()
-            << endl;
-  bool RetVal ;
+            << " " << Automaton()->StateName( State() ) << endl;
+  bool RetVal = false ;
   if ( IsDone() ) {
-    ControlState( SUPERV::VoidState ) ;
+//If loop we need to suspend also    ControlState( SUPERV::VoidState ) ;
+    ControlState( SUPERV::ToSuspendState ) ;
+    RetVal = true ;
     if ( _OutNode->IsDone() ) {
       ControlState( SUPERV::VoidState ) ;
+      RetVal = false ;
     }
-    RetVal = false ;
   }
   else if ( IsWaiting() || IsReady() ) {
     ControlState( SUPERV::ToSuspendState ) ;
@@ -458,47 +482,121 @@ bool GraphExecutor::InNode::Suspend() {
   else  if ( IsRunning() ) {
     ControlState( SUPERV::ToSuspendState ) ;
     if ( IsFactoryNode() || IsComputingNode() ) {
-      if ( !CORBA::is_nil( Component() ) ) {
-        try {
-          RetVal = Component()->Suspend_impl() ;
-       }
-        catch( ... ) {
-          cdebug << "InNode::Suspend() catched" << endl ;
-          State( SUPERV::ErroredState ) ;
-          _OutNode->State( SUPERV::ErroredState ) ;
-          RetVal = false ;
-       }
-        if ( RetVal ) {
-          if ( IsRunning() ) {
-            cdebug << pthread_self() << "GraphExecutor::InNode::Suspend_impl " << Name()
-                   << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
-            SendEvent( GraphExecutor::SuspendEvent ) ;
-            cdebug << pthread_self() << "GraphExecutor::InNode::Suspended_impl in Container"
-                   << Name() << " --> thread" << ThreadNo() << endl;
-          }
-          else if ( IsDone() ) {
-            ControlState( SUPERV::VoidState ) ;
-            RetVal = false ; // Too late ...
+// We have to suspend in the container of that node
+      int TrySuspend = 10 ;
+      while ( TrySuspend ) {
+        if ( !CORBA::is_nil( Component() ) ) {
+// We can call that component
+          try {
+            RetVal = Component()->Suspend_impl() ;
+         }
+          catch( ... ) {
+            cdebug << "InNode::Suspend() ERROR catched" << endl ;
+            State( GraphExecutor::ErroredState ) ;
+            _OutNode->State( GraphExecutor::ErroredState ) ;
+            RetVal = false ;
+            TrySuspend = 1 ;
+         }
+          cdebug << "Component()->Suspend_impl() returns status " << RetVal << endl ;
+          if ( RetVal ) {
+            if ( IsRunning() ) {
+              cdebug << pthread_self() << "GraphExecutor::InNode::Suspend_impl " << Name()
+                     << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
+              SendEvent( GraphExecutor::SuspendEvent ) ;
+              cdebug << pthread_self() << "GraphExecutor::InNode::Suspended_impl in Container"
+                     << Name() << " --> thread" << ThreadNo() << endl;
+              TrySuspend = 1 ;
+            }
+            else if ( IsDone() ) {
+              ControlState( SUPERV::VoidState ) ;
+              RetVal = false ; // Too late ...
+              TrySuspend = 1 ;
+            }
+            else {
+              cdebug << "InNode::Suspend component Suspended and !IsDone and !IsRunning !"
+                     << endl ;
+              MESSAGE("InNode::Suspend component Suspended and !IsDone and !IsRunning !") ;
+              TrySuspend = 1 ;
+           }
           }
           else {
-            cdebug << "component Suspended and !IsDone and !IsRunning !"
+// Suspend in the Container failed : it is always false if it is a Python Container
+            cdebug << "InNode::Suspend cannot Suspend component ! Python Component ?"
                    << endl ;
+            if ( TrySuspend == 1 ) {
+              if ( IsSuspended() ) {
+                RetVal = true ;
+             }
+              else {
+                RetVal = false ;
+             }
+           }
+          }
+        }
+        else {
+          cdebug << "InNode::Suspend with nilComponent while RunningState !. Loading Component ?"
+                 << endl ;
+// Wait for the end of loading of the component
+          while ( IsLoading() ) {
+            sleep( 1 ) ;
+         }
+          if ( TrySuspend == 1 ) {
+            if ( IsSuspended() ) {
+              RetVal = true ;
+           }
+            else {
+              RetVal = false ;
+           }
          }
         }
+        TrySuspend -= 1 ;
+        if ( TrySuspend ) {
+          sleep( 1 ) ;
+       }
       }
-      else {
-        cdebug << "Suspend cannot Suspend component !" << endl ;
-        RetVal = false ;
+    }
+    else if ( IsMacroNode() ) {
+// It should be like that but it is not completely implemented
+      GraphBase::Graph * aGraph = (GraphBase::Graph * ) GraphMacroNode()->CoupledNode() ;
+      RetVal = aGraph->GraphEditor()->Executor()->Suspend() ;
+      if ( RetVal ) {
+        State( GraphExecutor::SuspendedState ) ;
       }
     }
     else {
-      cdebug << "Suspend with nilComponent while RunningState !" << endl ;
-      RetVal = false ;
+// Now we can suspend an InLineNode with the handler of the SuperVision Container
+      if ( pthread_kill( _OutNode->MainThreadId() , SIGUSR2 ) == -1 ) {
+        perror("Suspend pthread_kill error") ;
+        State( GraphExecutor::ErroredState ) ;
+        _OutNode->State( GraphExecutor::ErroredState ) ;
+        RetVal = false ;
+      }
+      else {
+        RetVal = true ;
+      }
+      if ( RetVal ) {
+        if ( IsRunning() ) {
+          cdebug << pthread_self() << "GraphExecutor::InNode::Suspend " << Name()
+                 << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
+          SendEvent( GraphExecutor::SuspendEvent ) ;
+          cdebug << pthread_self() << "GraphExecutor::InNode::Suspended in SuperVision Container"
+                 << Name() << " --> thread" << ThreadNo() << endl;
+        }
+        else if ( IsDone() ) {
+          ControlState( SUPERV::VoidState ) ;
+          RetVal = false ; // Too late ...
+        }
+        else {
+          cdebug << "component Suspended and !IsDone and !IsRunning !"
+                 << endl ;
+       }
+      }
     }
   }
   else {
-    cdebug << "Suspend and !IsDone and !IsRunning and !IsWaiting ?"
-           << endl ;
+    cdebug << "Suspend and IsDone " << IsDone() << " and IsRunning " << IsRunning()
+           << " and IsWaiting " << IsWaiting() << " and IsReady " << IsReady()
+           << " ?" << endl ;
     RetVal = false ;
   }
   cdebug_out << "GraphExecutor::InNode::Suspend " << RetVal << " "
@@ -520,7 +618,9 @@ bool GraphExecutor::InNode::ContainerKill() {
 
 bool GraphExecutor::InNode::Kill() {
   cdebug_in << "GraphExecutor::InNode::Kill " << Name() << " " << ThreadNo() << " " 
-            << Automaton()->StateName( State() ) << endl;
+            << Automaton()->StateName( State() ) << " Threads " << _OutNode->Threads()
+            << " SuspendedThreads " << _OutNode->SuspendedThreads()
+            << " EventQSize " << _OutNode->EventQSize() << endl;
   bool RetVal ;
   if ( IsDone() ) {
     ControlState( SUPERV::ToKillState ) ; // if loop
@@ -540,57 +640,137 @@ bool GraphExecutor::InNode::Kill() {
     else {
       if ( IsRunning() ) {
         if ( IsFactoryNode() || IsComputingNode() ) {
-          if ( !CORBA::is_nil( Component() ) ) {
-            try {
-              RetVal = Component()->Kill_impl() ;
-           }
-            catch( ... ) {
-              cdebug << "InNode::Suspend() catched" << endl ;
-              State( SUPERV::ErroredState ) ;
-              _OutNode->State( SUPERV::ErroredState ) ;
-              RetVal = false ;
-           }
-            cdebug << "Component()->Kill_impl() returns status " << RetVal << endl ;
-            RetVal = true ;
-            if ( IsRunning() ) {
-              cdebug << pthread_self() << "GraphExecutor::InNode::Kill_impl " << Name()
-                     << " --> thread" << ThreadNo() << " SuspendEvent " << endl;
-              SendEvent( GraphExecutor::KillEvent ) ;
-              cdebug << pthread_self() << "GraphExecutor::InNode::Killed_impl in Container"
-                     << Name() << " --> thread" << ThreadNo() << endl;
-           }
-            else if ( IsDone() ) {
-              ControlState( SUPERV::VoidState ) ;
-              RetVal = false ; // Too late ...
+// We have to suspend in the container of that node
+          int TryKill = 10 ;
+          while ( TryKill ) {
+            if ( !CORBA::is_nil( Component() ) ) {
+// We can call that component
+              try {
+                RetVal = Component()->Kill_impl() ;
+             }
+              catch( ... ) {
+                cdebug << "InNode::Kill_impl ERROR catched" << endl ;
+                State( GraphExecutor::ErroredState ) ;
+                _OutNode->State( GraphExecutor::ErroredState ) ;
+                RetVal = false ;
+                TryKill = 1 ;
+             }
+              cdebug << "Component()->Kill_impl() returns status " << RetVal << endl ;
+              if ( RetVal ) {
+                if ( IsRunning() ) {
+                  cdebug << pthread_self() << "GraphExecutor::InNode::Kill_impl " << Name()
+                         << " --> thread" << ThreadNo() << " KillEvent " << endl;
+                  SendEvent( GraphExecutor::KillEvent ) ;
+                  cdebug << pthread_self() << "GraphExecutor::InNode::Killed_impl in Container"
+                         << Name() << " --> thread" << ThreadNo() << endl;
+                  TryKill = 1 ;
+               }
+                else if ( IsDone() ) {
+                  ControlState( SUPERV::VoidState ) ;
+                  RetVal = false ; // Too late ...
+                  TryKill = 1 ;
+               }
+                else {
+                  cdebug << "Kill component Killed and !IsDone and !IsRunning !"
+                         << endl ;
+                  TryKill = 1 ;
+               }
+             }
+              else {
+//  Kill in the Container failed : it is always false if it is a Python Container
+                cdebug << "InNode::Suspend cannot  Kill component ! Python Component ?"
+                       << endl ;
+                if ( TryKill == 1 ) {
+                  if ( IsKilled() ) {
+                    RetVal = true ;
+                 }
+                  else {
+                    RetVal = false ;
+                 }
+               }
+             }
            }
             else {
-              cdebug << "component Killed and !IsDone and !IsRunning !"
+              cdebug << "InNode::Kill with nilComponent while RunningState !. Loading Component ?"
                      << endl ;
+// Wait for the end of loading of the component
+              while ( IsLoading() ) {
+                sleep( 1 ) ;
+             }
+              if ( TryKill == 1 ) {
+                if ( IsKilled() ) {
+                  RetVal = true ;
+               }
+                else {
+                  RetVal = false ;
+               }
+             }
            }
+            TryKill -= 1 ;
+            if ( TryKill ) {
+              sleep( 1 ) ;
+            }
          }
-          else {
-            cdebug << "Kill with nilComponent cannot Kill component !" << endl ;
+       }
+        else if ( IsMacroNode() ) {
+// It should be like that but it is not completely implemented
+          GraphBase::Graph * aGraph = (GraphBase::Graph * ) GraphMacroNode()->CoupledNode() ;
+          RetVal = aGraph->GraphEditor()->Executor()->Kill() ;
+          if ( RetVal ) {
+            State( GraphExecutor::KilledState ) ;
+         }
+       }
+        else {
+//PAL6886
+// Now we can kill an InLineNode with the handler of the SuperVision Container
+          cdebug << pthread_self() << "Kill of InLineNode " << Name() << " MainThreadId "
+                 << _OutNode->MainThreadId() << " :" << endl ;
+          MESSAGE( pthread_self() << "Kill of InLineNode " << Name() << " MainThreadId "
+                 << _OutNode->MainThreadId() << " :" ) ;
+          if ( pthread_kill( _OutNode->MainThreadId() , SIGINT ) == -1 ) {
+// python signals run only in main thread ...
+            perror("Kill pthread_kill error") ;
+            State( GraphExecutor::ErroredState ) ;
+            _OutNode->State( GraphExecutor::ErroredState ) ;
             RetVal = false ;
          }
+          else {
+            cdebug << pthread_self() << "pthread_kill of InLineNode " << Name()
+                   << " done. MainThreadId " << _OutNode->MainThreadId() << endl ;
+            MESSAGE( pthread_self() << "pthread_kill of InLineNode " << Name()
+                   << " done. MainThreadId " << _OutNode->MainThreadId() ) ;
+            RetVal = true ;
+         }
        }
       }
       else if ( IsSuspended() ) {
         cdebug << pthread_self() << "GraphExecutor::InNode::Kill " << Name()
                << " --> thread" << ThreadNo() << " Resume()" << endl;
-        Resume() ;
-        RetVal = true ;
+        if ( Resume() ) {
+          RetVal = Kill() ;
+       }
+        else {
+          RetVal = false ;
+       }
       }
       else if ( IsWaiting() ) {
+        RetVal = false ;
+      }
+      else if ( IsReady() ) {
         RetVal = true ;
       }
       else {
-        cdebug << "Kill and !IsDone and !IsRunning and !IsWaiting ?"
-               << endl ;
+       cdebug << "Kill and IsDone " << IsDone() << " and IsRunning " << IsRunning()
+              << " and IsWaiting " << IsWaiting() << " and IsReady " << IsReady()
+              << " ?" << endl ;
         RetVal = false ;
       }
     }
   }
-  cdebug_out << "GraphExecutor::InNode::Kill" << endl ;
+  cdebug_out << "GraphExecutor::InNode::Kill " << Name() << " " << ThreadNo() << " " 
+             << Automaton()->StateName( State() ) << " Threads " << _OutNode->Threads()
+             << " SuspendedThreads " << _OutNode->SuspendedThreads()
+             << " EventQSize " << _OutNode->EventQSize() << endl ;
   return RetVal ;
 }
 
@@ -650,9 +830,9 @@ bool GraphExecutor::InNode::Stop() {
               RetVal = Component()->Stop_impl() ;
            }
             catch( ... ) {
-              cdebug << "InNode::Stop() catched" << endl ;
-              State( SUPERV::ErroredState ) ;
-              _OutNode->State( SUPERV::ErroredState ) ;
+              cdebug << "InNode::Stop() ERROR catched" << endl ;
+              State( GraphExecutor::ErroredState ) ;
+              _OutNode->State( GraphExecutor::ErroredState ) ;
               RetVal = false ;
            }
             if ( RetVal ) {
@@ -670,7 +850,7 @@ bool GraphExecutor::InNode::Stop() {
            }
          }
           else {
-            cdebug << "Suspend cannot Suspend component !" << endl ;
+            cdebug << "Suspend cannot Stop component ! Python Component ?" << endl ;
             RetVal = false ;
          }
        }
@@ -722,28 +902,62 @@ bool GraphExecutor::InNode::Resume() {
             << Automaton()->StateName( State() ) << endl;
   bool RetVal = false ;
   if ( IsSuspended() ) {
-    if ( State() == SUPERV::SuspendedReadyState ) {
+    if ( State() == GraphExecutor::SuspendedReadyState ) {
       ResumeAction( GraphExecutor::ToResumeEvent ) ;
       RetVal = true ;
     }
-    else if ( State() == SUPERV::SuspendedExecutingState ) {
+    else if ( State() == GraphExecutor::SuspendedExecutingState ) {
       if ( IsFactoryNode() || IsComputingNode() ) {
+        if ( pthread_mutex_lock( &_MutexWait ) ) {
+          perror("ResumeAction pthread_mutex_lock ") ;
+          exit( 0 ) ;
+        }
         try {
           RetVal = Component()->Resume_impl() ;
+          if ( RetVal ) {
+            State( GraphExecutor::ExecutingState ) ;
+         }
        }
         catch( ... ) {
-          cdebug << "InNode::Resume() catched" << endl ;
-          State( SUPERV::ErroredState ) ;
-          _OutNode->State( SUPERV::ErroredState ) ;
+          cdebug << "InNode::Resume() ERROR catched" << endl ;
+          State( GraphExecutor::ErroredState ) ;
+          _OutNode->State( GraphExecutor::ErroredState ) ;
           RetVal = false ;
        }
+        if ( pthread_mutex_unlock( &_MutexWait ) ) {
+          perror("ResumeAction pthread_mutex_unlock ") ;
+          exit( 0 ) ;
+        }
+      }
+      else if ( IsMacroNode() ) {
+        cdebug << "Suspend of MacroNode not yet implemented ? Trying" << endl ;
+        GraphBase::Graph * aGraph = (GraphBase::Graph * ) GraphMacroNode()->CoupledNode() ;
+        RetVal = aGraph->GraphEditor()->Executor()->Resume() ;
+        if ( RetVal ) {
+          State( GraphExecutor::ExecutingState ) ;
+       }
+      }
+      else {
+// Resume of InLinePythonNode in the Node of the SuperVisionContainer ...
+        cdebug << ThreadNo() << "/" << pthread_self()
+               << "Resume of InLineNode pthread_kill" << Name() << endl ;
+        if ( pthread_kill( _OutNode->MainThreadId() , SIGCONT ) == -1 ) {
+          perror("Resume pthread_kill error") ;
+          State( GraphExecutor::ErroredState ) ;
+          _OutNode->State( GraphExecutor::ErroredState ) ;
+          RetVal = false ;
+        }
+        else {
+          State( GraphExecutor::ExecutingState ) ;
+          RetVal = true ;
+        }
       }
     }
-    else if ( State() == SUPERV::SuspendedSuccessedState ) {
+    else if ( State() == GraphExecutor::SuspendedSuccessedState ) {
       ResumeAction( GraphExecutor::ResumeEvent ) ;
       RetVal = true ;
     }
-    else if ( State() == SUPERV::SuspendedErroredState ) {
+    else if ( State() == GraphExecutor::SuspendedErroredState ) {
       ResumeAction( GraphExecutor::ResumeEvent ) ;
       RetVal = true ;
     }
@@ -765,13 +979,13 @@ bool GraphExecutor::InNode::Resume() {
 #if 0
   if ( ControlState() == SUPERV::ToSuspendRunState ||
        ( ControlState() == SUPERV::ToSuspendState &&
-         State() == SUPERV::SuspendedReadyState) ) {
+         State() == GraphExecutor::SuspendedReadyState) ) {
     if ( IsSuspended() ) {
-      if ( State() == SUPERV::SuspendedReadyState ) {
+      if ( State() == GraphExecutor::SuspendedReadyState ) {
         ResumeAction() ;
         RetVal = true ;
       }
-      else if ( State() == SUPERV::SuspendedExecutingState ) {
+      else if ( State() == GraphExecutor::SuspendedExecutingState ) {
         ResumeAction() ;
         RetVal = Component()->Resume_impl() ;
       }
@@ -797,13 +1011,13 @@ bool GraphExecutor::InNode::Resume() {
   }
   else if ( ControlState() == SUPERV::ToSuspendDoneState ||
             ( ControlState() == SUPERV::ToSuspendState &&
-              State() == SUPERV::SuspendedSuccessedState) ) {
+              State() == GraphExecutor::SuspendedSuccessedState) ) {
     if ( IsSuspended() ) {
-      if ( State() == SUPERV::SuspendedSuccessedState ) {
+      if ( State() == GraphExecutor::SuspendedSuccessedState ) {
         ResumeAction() ;
         RetVal = true ;
       }
-      else if ( State() == SUPERV::SuspendedErroredState ) {
+      else if ( State() == GraphExecutor::SuspendedErroredState ) {
         ResumeAction() ;
         RetVal = true ;
       }
@@ -829,7 +1043,8 @@ bool GraphExecutor::InNode::Resume() {
     }
   }
 #endif
-  cdebug_out << "GraphExecutor::InNode::Resume " << RetVal << endl ;
+  cdebug_out << "GraphExecutor::InNode::Resume " << Name() << " " << RetVal << " "
+             << Automaton()->StateName( State() ) << endl ;
   return RetVal ;
 }
 
@@ -849,7 +1064,7 @@ bool GraphExecutor::InNode::ReStart( const char * AtNodeName ,
   }
   else if ( IsSuspended() ) {
     if ( strcmp( AtNodeName , Name() ) ) {
-      aRestartNode->State( SUPERV::SuspendedSuccessedState ) ;
+      aRestartNode->State( GraphExecutor::SuspendedSuccessedState ) ;
     }
     if ( AndSuspend ) {
       ReStartAction( aRestartNode , GraphExecutor::ReStartAndSuspendEvent ) ;
@@ -866,14 +1081,14 @@ bool GraphExecutor::InNode::ReStart( const char * AtNodeName ,
 bool GraphExecutor::InNode::IsWaiting() {
   bool aret = false ;
 //  cdebug_in << "GraphExecutor::InNode::IsWaiting " << Name() << endl;
-  SUPERV::AutomatonState aState = State() ;
-  if ( aState == SUPERV::DataUndefState ||
-       aState == SUPERV::DataWaitingState ||
-       aState == SUPERV::SuspendedReadyState )
-//       aState == SUPERV::SuspendedExecutingState ||
-//       aState == SUPERV::SuspendedSuccessedState ||
-//       aState == SUPERV::SuspendedErroredState ||
-//       aState == SUPERV::SuspendedState
+  GraphExecutor::AutomatonState aState = State() ;
+  if ( aState == GraphExecutor::DataUndefState ||
+       aState == GraphExecutor::DataWaitingState ||
+       aState == GraphExecutor::SuspendedReadyState )
+//       aState == GraphExecutor::SuspendedExecutingState ||
+//       aState == GraphExecutor::SuspendedSuccessedState ||
+//       aState == GraphExecutor::SuspendedErroredState ||
+//       aState == GraphExecutor::SuspendedState
     aret = true ;
 //  cdebug_out << "GraphExecutor::InNode::IsWaiting" << endl ;
   return aret ;
@@ -882,11 +1097,11 @@ bool GraphExecutor::InNode::IsWaiting() {
 bool GraphExecutor::InNode::IsReady() {
   bool aret = false ;
 //  cdebug_in << "GraphExecutor::InNode::IsReady " << Name() << endl;
-  SUPERV::AutomatonState aState = State() ;
-  if ( aState == SUPERV::DataUndefState ||
-       aState == SUPERV::DataWaitingState ||
-       aState == SUPERV::DataReadyState ||
-       aState == SUPERV::ResumedReadyState )
+  GraphExecutor::AutomatonState aState = State() ;
+//  if ( aState == GraphExecutor::DataUndefState ||
+//       aState == GraphExecutor::DataWaitingState ||
+  if ( aState == GraphExecutor::DataReadyState ||
+       aState == GraphExecutor::ResumedReadyState )
     aret = true ;
 //  cdebug_out << "GraphExecutor::InNode::IsReady" << endl ;
   return aret ;
@@ -895,9 +1110,9 @@ bool GraphExecutor::InNode::IsReady() {
 bool GraphExecutor::InNode::IsRunning() {
   bool aret = false ;
 //  cdebug_in << "GraphExecutor::InNode::IsRunning " << Name() << endl;
-  SUPERV::AutomatonState aState = State() ;
-  if ( aState == SUPERV::ExecutingState ||
-       aState == SUPERV::ResumedExecutingState )
+  GraphExecutor::AutomatonState aState = State() ;
+  if ( aState == GraphExecutor::ExecutingState ||
+       aState == GraphExecutor::ResumedExecutingState )
     aret = true ;
 //  cdebug_out << "GraphExecutor::InNode::IsRunning" << endl ;
   return aret ;
@@ -906,21 +1121,21 @@ bool GraphExecutor::InNode::IsRunning() {
 bool GraphExecutor::InNode::IsDone() {
   bool aret = false ;
 //  cdebug_in << "GraphExecutor::InNode::IsDone " << Name() << endl;
-  SUPERV::AutomatonState aState = State() ;
-  if ( aState == SUPERV::KilledReadyState ||
-       aState == SUPERV::StoppedReadyState ||
-       aState == SUPERV::KilledExecutingState ||
-       aState == SUPERV::StoppedExecutingState ||
-       aState == SUPERV::SuspendedSuccessedState ||
-       aState == SUPERV::SuspendedErroredState ||
-//       aState == SUPERV::SuccessedExecutingState ||
-//       aState == SUPERV::ErroredExecutingState ||
-       aState == SUPERV::SuccessedState ||
-       aState == SUPERV::ErroredState ||
-       aState == SUPERV::ResumedSuccessedState ||
-       aState == SUPERV::ResumedErroredState ||
-       aState == SUPERV::KilledSuccessedState ||
-       aState == SUPERV::StoppedSuccessedState )
+  GraphExecutor::AutomatonState aState = State() ;
+  if ( aState == GraphExecutor::KilledReadyState ||
+       aState == GraphExecutor::StoppedReadyState ||
+       aState == GraphExecutor::KilledExecutingState ||
+       aState == GraphExecutor::StoppedExecutingState ||
+       aState == GraphExecutor::SuspendedSuccessedState ||
+       aState == GraphExecutor::SuspendedErroredState ||
+//       aState == GraphExecutor::SuccessedExecutingState ||
+//       aState == GraphExecutor::ErroredExecutingState ||
+       aState == GraphExecutor::SuccessedState ||
+       aState == GraphExecutor::ErroredState ||
+       aState == GraphExecutor::ResumedSuccessedState ||
+       aState == GraphExecutor::ResumedErroredState ||
+       aState == GraphExecutor::KilledSuccessedState ||
+       aState == GraphExecutor::StoppedSuccessedState )
     aret = true ;
 //  cdebug_out << "GraphExecutor::InNode::IsDone" << endl ;
   return aret ;
@@ -929,11 +1144,12 @@ bool GraphExecutor::InNode::IsDone() {
 bool GraphExecutor::InNode::IsSuspended() {
   bool aret = false ;
 //  cdebug_in << "GraphExecutor::InNode::IsSuspended " << Name() << endl;
-  SUPERV::AutomatonState aState = State() ;
-  if ( aState == SUPERV::SuspendedReadyState ||
-       aState == SUPERV::SuspendedExecutingState ||
-       aState == SUPERV::SuspendedSuccessedState ||
-       aState == SUPERV::SuspendedErroredState )
+  GraphExecutor::AutomatonState aState = State() ;
+  if ( aState == GraphExecutor::SuspendedReadyState ||
+       aState == GraphExecutor::SuspendedExecutingState ||
+       aState == GraphExecutor::SuspendedSuccessedState ||
+       aState == GraphExecutor::SuspendedErroredState ||
+       aState == GraphExecutor::SuspendedState )
     aret = true ;
 //  cdebug_out << "GraphExecutor::InNode::IsSuspended" << endl ;
   return aret ;
@@ -941,12 +1157,12 @@ bool GraphExecutor::InNode::IsSuspended() {
 bool GraphExecutor::InNode::IsKilled() {
   bool aret = false ;
 //  cdebug_in << "GraphExecutor::InNode::IsKilled " << Name() << endl;
-  SUPERV::AutomatonState aState = State() ;
-  if ( aState == SUPERV::KilledReadyState ||
-       aState == SUPERV::KilledExecutingState ||
-       aState == SUPERV::KilledSuccessedState ||
-       aState == SUPERV::KilledErroredState ||
-       aState == SUPERV::KilledState )
+  GraphExecutor::AutomatonState aState = State() ;
+  if ( aState == GraphExecutor::KilledReadyState ||
+       aState == GraphExecutor::KilledExecutingState ||
+       aState == GraphExecutor::KilledSuccessedState ||
+       aState == GraphExecutor::KilledErroredState ||
+       aState == GraphExecutor::KilledState )
     aret = true ;
 //  cdebug_out << "GraphExecutor::InNode::IsKilled" << endl ;
   return aret ;
@@ -954,12 +1170,12 @@ bool GraphExecutor::InNode::IsKilled() {
 bool GraphExecutor::InNode::IsStopped() {
   bool aret = false ;
 //  cdebug_in << "GraphExecutor::InNode::IsStopped " << Name() << endl;
-  SUPERV::AutomatonState aState = State() ;
-  if ( aState == SUPERV::StoppedReadyState ||
-       aState == SUPERV::StoppedExecutingState ||
-       aState == SUPERV::StoppedSuccessedState ||
-       aState == SUPERV::StoppedErroredState ||
-       aState == SUPERV::StoppedState )
+  GraphExecutor::AutomatonState aState = State() ;
+  if ( aState == GraphExecutor::StoppedReadyState ||
+       aState == GraphExecutor::StoppedExecutingState ||
+       aState == GraphExecutor::StoppedSuccessedState ||
+       aState == GraphExecutor::StoppedErroredState ||
+       aState == GraphExecutor::StoppedState )
     aret = true ;
 //  cdebug_out << "GraphExecutor::InNode::IsStopped" << endl ;
   return aret ;
@@ -996,12 +1212,14 @@ bool GraphExecutor::InNode::StateWait( SUPERV::GraphState aState ) {
               << " " << Automaton()->StateName( _currentState )
               << " pthread_cond_wait _RunningWait " << Name() << endl ;
     while ( !RetVal && !IsDone() ) {
-      cdebug << pthread_self() << " pthread_cond_wait RunningWait" << endl ;
+      cdebug << pthread_self() << " pthread_cond_wait RunningWait " << Name() << endl ;
       pthread_cond_wait( &_RunningWait , &_MutexWait );
-      RetVal = IsRunning() ;
+//We may have pthread_cond_waited but !IsRunning and !IsDone :
+      RetVal = IsRunning() || State() == GraphExecutor::SuccessedExecutingState ||
+               State() == GraphExecutor::ErroredExecutingState ;
       cdebug << pthread_self() << " pthread_cond_waited RunningWait "
              << Automaton()->StateName( _currentState ) << " " << RetVal
-             << endl ;
+             << " " << Name() << endl ;
     }
     cdebug_out << pthread_self() << " StateWait( Running ) " << RetVal
                << " " << Automaton()->StateName( _currentState )
@@ -1045,7 +1263,7 @@ bool GraphExecutor::InNode::StateWait( SUPERV::GraphState aState ) {
     break ;
   }
   default : {
-    cdebug << " GraphExecutor::OutNode::StateWait Error Undefined State : "
+    cdebug << " SUPERV::OutNode::StateWait Error Undefined State : "
            << aState << endl ;
   }
   }
@@ -1065,9 +1283,12 @@ bool GraphExecutor::InNode::ReadyWait() {
 }
 
 bool GraphExecutor::InNode::RunningWait() {
-//  cdebug_in << "GraphExecutor::InNode::RunningWait " << Name() << endl;
+  cdebug_in << pthread_self() << "GraphExecutor::InNode::RunningWait " << Name()
+            << " " << Automaton()->StateName( State() ) << endl;
   bool aret ;
   aret = StateWait( SUPERV::RunningState ) ;
+  cdebug_out << pthread_self() << "GraphExecutor::InNode::RunningWait " << Name()
+             << " " << Automaton()->StateName( State() ) << endl;
   return aret ;
 }
 
@@ -1085,18 +1306,21 @@ bool GraphExecutor::InNode::SuspendedWait() {
   return aret ;
 }
 
-void GraphExecutor::InNode::InitialState( GraphExecutor::OutNode * theOutNode )
+void GraphExecutor::InNode::InitialState()
 {
   cdebug_in << "GraphExecutor::InNode::InitialState Node " << Name() << endl;
 
-  _OutNode = theOutNode ;
-
   int i;
   _ControlState = SUPERV::VoidState ;
   CreateNewThread( false ) ;
   CreateNewThreadIf( false ) ;
   _SuspendSync = false ;
   _ResumeSync = false ;
+
+  // asv : 13.12.04 : "Loading" state is ON (and OFF eventially) only for Computing, Factory, Inline nodes
+  if ( !IsMacroNode() )
+    IsLoading( true ) ;
+
 //  ThreadNo( pthread_self() ) ;
   ThreadNo( 0 ) ;
 
@@ -1123,33 +1347,46 @@ void GraphExecutor::InNode::InitialState( GraphExecutor::OutNode * theOutNode )
       *anAny <<= (long ) 1 ;
       anOutPort->Value( anAny ) ;
     }
+// JR 15_09_2004 if backward link from GOTONode or EndLoopNode ==> DataConnected
     else if ( anInPort->IsGate() && anOutPort ) {
-      if ( IsComputingNode() || IsFactoryNode() ) {
-        anOutPort->State( SUPERV::WaitingState ) ;
-        anOutPort->Done( false ) ;
-      }
-      else if ( IsOneOfInLineNodes() ) {
+      anOutPort->State( SUPERV::WaitingState ) ;
+      anOutPort->Done( false ) ;
+      const GraphBase::ComputingNode * aFromNode =  _OutNode->Graph()->GetGraphNode( anOutPort->NodeName() ) ; 
+      if ( aFromNode->IsGOTONode() || aFromNode->IsEndLoopNode() ) { // ASV: bug with synchronization of Inline nodes (via Gate ports) fixed.  
+                                       // before was "else if ( IsOneOfInlineNodes() )"
+                                      // IsOneOfInline() == ( Inline || IsOneOfGOTO() ), so Inline are removed..
         anOutPort->PortStatus( DataConnected );
         anOutPort->State( SUPERV::ReadyState ) ;
         anOutPort->Done( true ) ;
       }
     }
-//    if ( ( anInPort->IsGate() || anInPort->IsBus() ) && anOutPort == NULL ) {
     if ( anInPort->IsGate() && anOutPort == NULL ) {
       Pc-- ;
+      cdebug << "InPort" << i << " " << anInPort->PortName() << " Not connected Pc " << Pc << endl ;
     }
     else if ( anOutPort ) {
       if ( anOutPort->IsDataConnected() || anOutPort->IsDataStream() ) {
         Pc-- ;
-      }
-      if ( anOutPort->IsDataConnected() || anOutPort->IsDataStream() ) {
         anOutPort->State( SUPERV::ReadyState ) ;
         anOutPort->Done( true ) ;
+        cdebug << "InPort" << i << " " << anInPort->PortName() << " " << anInPort->PortStatus()
+               << " " << theAutomaton->StateName( anOutPort->State() ) << " Pc " << Pc << endl ;
       }
       else if ( anOutPort->IsPortConnected() ) {
         anOutPort->State( SUPERV::WaitingState ) ;
         anOutPort->Done( false ) ;
+        cdebug << "InPort" << i << " " << anInPort->PortName() << " " << " " << anInPort->PortStatus()
+               << " " << theAutomaton->StateName( anOutPort->State() ) << " Pc " << Pc << endl ;
       }
+      else {
+        cdebug << "InPort" << i << " " << anInPort->PortName() << " " << anInPort->PortStatus()
+               << " OutPort " << anOutPort->NodeName() << " " << anOutPort->PortName() << " "
+               << theAutomaton->StateName( anOutPort->State() ) << " Pc " << Pc << endl ;
+      }
+    }
+    else {
+      cdebug << "InPort" << i << " " << anInPort->PortName() << " " << " " << anInPort->PortStatus()
+             << " no corresponding OutPort Pc " << Pc << endl ;
     }
     if ( anOutPort ) {
       if ( !anOutPort->IsDataStream() || anInPort->IsDataStream() ) {
@@ -1158,12 +1395,17 @@ void GraphExecutor::InNode::InitialState( GraphExecutor::OutNode * theOutNode )
                << " with state " << theAutomaton->StateName( anOutPort->State() ) << endl ;
         GetChangeNodeInPort(i)->State( anOutPort->State() ) ;
       }
-      else {
+      else if ( anOutPort->IsDataConnected() ) {
         cdebug << "InPort" << i << " state change : " << anInPort->PortName() << " from OutPort "
                << anOutPort->PortName() << " from Node " << anOutPort->NodeName()
                << " with state ReadyState" << endl ;
         GetChangeNodeInPort(i)->State( SUPERV::ReadyState ) ;
       }
+      else {
+        cdebug << "InPort" << i << " state NOT changed : " << anInPort->PortName() << " from OutPort "
+               << anOutPort->PortName() << " " << anOutPort->PortStatus() << " from Node " << anOutPort->NodeName()
+               << " with state " << anOutPort->State() << endl ;
+      }
     }
     if ( anOutPort ) {
       cdebug << "InPort" << i << " : " << anInPort->PortName() << " from OutPort "
@@ -1184,8 +1426,8 @@ void GraphExecutor::InNode::InitialState( GraphExecutor::OutNode * theOutNode )
     }
   }
 
-  _currentState = Pc > 0 ? SUPERV::DataWaitingState 
-                         : SUPERV::DataReadyState ;
+  _currentState = Pc > 0 ? GraphExecutor::DataWaitingState 
+                         : GraphExecutor::DataReadyState ;
   if ( Pc == GetNodeInPortsSize() ) {
     _OutNode->PushEvent( this , GraphExecutor::NoDataReadyEvent ,
                          _currentState ) ; 
@@ -1289,7 +1531,9 @@ bool GraphExecutor::InNode::InitPythonFunctions(bool WithErr ) {
 
 const long GraphExecutor::InNode::CpuUsed( bool tot ) {
   CORBA::Long cpu = 0 ;
-//  cdebug_in << "GraphExecutor::InNode::CpuUsed( " << tot << " )" << Name() << endl ;
+  cout << "Begin CpuUsed " << Name() << " CpuUsed : " << cpu << " State "
+       << theAutomaton->StateName( _currentState ) << endl ;
+  cdebug_in << "GraphExecutor::InNode::CpuUsed( " << tot << " )" << Name() << endl ;
   if ( IsOneOfInLineNodes() ) {
 //    cdebug << "CpuUsed " << Name() << " --> PyCpuUsed()" << endl ;
 //    cout << "CpuUsed " << Name() << " --> PyCpuUsed()" << endl ;
@@ -1304,14 +1548,15 @@ const long GraphExecutor::InNode::CpuUsed( bool tot ) {
       }
       catch ( ... ) {
         cdebug << "CpuUsed " << Name() << " --> Component()->CpuUsed_impl() ERROR catched " << endl ;
-        State( SUPERV::ErroredState ) ;
-        _OutNode->State( SUPERV::ErroredState ) ;
+        State( GraphExecutor::ErroredState ) ;
+        _OutNode->State( GraphExecutor::ErroredState ) ;
         cpu = 0 ;
       }
     }
   }
-//  cdebug_out << "GraphExecutor::InNode::CpuUsed " << Name() << " CpuUsed : " << cpu << endl ;
-//  cout << "CpuUsed " << Name() << " CpuUsed : " << cpu << endl ;
+  cdebug_out << "GraphExecutor::InNode::CpuUsed " << Name() << " CpuUsed : " << cpu << endl ;
+  cout << "End CpuUsed " << Name() << " CpuUsed : " << cpu << " State "
+       << theAutomaton->StateName( _currentState ) << endl ;
   return cpu ;
 }
 
@@ -1367,3 +1612,13 @@ void GraphExecutor::InNode::SetPyCpuUsed() {
 //         << _PyCpuUsed << endl ;
 }
 
+void GraphExecutor::InNode::IsLoading( bool Loading ) {
+  _Loading = Loading ;
+  
+  // asv : 09.12.04 : "Bugs and Improvents" 2.19 : how it works: 
+  // LoadingState is returned by OutNode::State( NodeName ) if InNode->IsLoading()
+  // after Loading is finished (here below), ExecutingState must be pushed for GUI.  
+  if ( !Loading )
+    _OutNode->PushEvent( this, GraphExecutor::ExecuteEvent, GraphExecutor::ExecutingState );
+}
+