]> Creatis software - bbtk.git/blobdiff - kernel/src/bbtkBlackBox.cxx
bbtk now depends on crea !
[bbtk.git] / kernel / src / bbtkBlackBox.cxx
index d2137752f2e8aee1d3084543d6c786427e001b71..a4dea22c8624d2e0959d574c573799a54122dd72 100644 (file)
@@ -1,21 +1,32 @@
-/*=========================================================================
-                                                                                
-Program:   bbtk
-Module:    $RCSfile: bbtkBlackBox.cxx,v $
-Language:  C++
-Date:      $Date: 2008/06/19 09:46:41 $
-Version:   $Revision: 1.21 $
-                                                                                
-Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
-l'Image). All rights reserved. See doc/license.txt or
-http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
-                                                                                
-This software is distributed WITHOUT ANY WARRANTY; without even
-the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-PURPOSE.  See the above copyright notices for more information.
-                                                                                
+/*=========================================================================                                                                               
+  Program:   bbtk
+  Module:    $RCSfile: bbtkBlackBox.cxx,v $
+  Language:  C++
+  Date:      $Date: 2008/12/11 15:30:04 $
+  Version:   $Revision: 1.38 $
 =========================================================================*/
 
+/* ---------------------------------------------------------------------
+
+* Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
+* Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
+*
+*  This software is governed by the CeCILL-B license under French law and 
+*  abiding by the rules of distribution of free software. You can  use, 
+*  modify and/ or redistribute the software under the terms of the CeCILL-B 
+*  license as circulated by CEA, CNRS and INRIA at the following URL 
+*  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
+*  or in the file LICENSE.txt.
+*
+*  As a counterpart to the access to the source code and  rights to copy,
+*  modify and redistribute granted by the license, users are provided only
+*  with a limited warranty  and the software's author,  the holder of the
+*  economic rights,  and the successive licensors  have only  limited
+*  liability. 
+*
+*  The fact that you are presently reading this means that you have had
+*  knowledge of the CeCILL-B license and that you accept its terms.
+* ------------------------------------------------------------------------ */                                                                         
 
 /**
  *  \file 
@@ -25,6 +36,7 @@ PURPOSE.  See the above copyright notices for more information.
 #include "bbtkPackage.h"
 #include "bbtkMessageManager.h"
 #include "bbtkFactory.h"
+#include "bbtkBlackBoxOutputConnector.h"
 
 #include "bbtkConfigurationFile.h"
 #include "bbtkWxBlackBox.h"
@@ -39,7 +51,7 @@ namespace bbtk
 
   static bool bbmgSomeBoxExecuting = false;
   static bool bbmgFreezeExecution = false;
-  static std::set<BlackBox::Pointer> bbmgExecutionList;
+  static std::set<BlackBox::WeakPointer> bbmgExecutionList;
 
   //=========================================================================
   BlackBox::Deleter::Deleter()
@@ -90,11 +102,13 @@ namespace bbtk
 
   //=========================================================================
   BlackBox::BlackBox(const std::string &name) 
-    : bbmName(name), 
-      bbmStatus(MODIFIED), 
-      bbmBoxProcessMode("Pipeline"),
-      bbmParent()
-
+    : 
+    //    bbmStatus(MODIFIED), 
+    bbmExecuting(false),
+    bbmName(name),
+    bbmBoxProcessMode("Pipeline"),
+    bbmParent()
+    
   {
     bbtkDebugMessage("object",4,"==> BlackBox::BlackBox(\""
                     <<name<<"\")"<<std::endl);
@@ -109,8 +123,10 @@ namespace bbtk
 
   //=========================================================================
   BlackBox::BlackBox(BlackBox& from, const std::string &name) 
-    : bbmName(name), 
-      bbmStatus(from.bbmStatus), 
+    :
+    //    bbmStatus(from.bbmStatus), 
+      bbmExecuting(false),
+      bbmName(name), 
       bbmBoxProcessMode(from.bbmBoxProcessMode),
       bbmParent()
 
@@ -137,37 +153,6 @@ namespace bbtk
   //=========================================================================
 
 
-  //=========================================================================
-  /// Main processing method of the box.
-  void BlackBox::bbExecute(bool force)
-  {
-    bbtkDebugMessageInc("process",2,
-                       "=> BlackBox::bbExecute() ["
-                       <<bbGetFullName()<<"]"<<std::endl);
-       wxBusyCursor wait;
-    //EED Wx::BeginBusyCursor();
-
-    // If execution frozen : return
-    if (bbGlobalGetFreezeExecution()) 
-      {
-       bbtkDebugMessage("process",2,
-                        " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
-      }
-
-    // If force is true then update is triggered even if the box is UPTODATE
-    if (force) bbSetModifiedStatus();
-
-    // Calls the main recursive update method 
-    bbBackwardUpdate(Connection::Pointer());
-
-    //EED Wx::EndBusyCursor();
-
-    bbtkDebugMessageDec("process",2,
-                       "<= BlackBox::bbExecute() ["
-                       <<bbGetFullName()<<"]"<<std::endl);
-  }
-  //=========================================================================
 
   //=========================================================================
   std::string BlackBox::bbGetFullName() const
@@ -323,7 +308,7 @@ namespace bbtk
   /// Copies the input / output values from another box
   void BlackBox::bbCopyIOValues(BlackBox& from)
   {
-    bbtkDebugMessageInc("Kernel",9,
+    bbtkDebugMessageInc("Kernel",1,
                        "BlackBox::bbCopyIOValues("
                        <<from.bbGetFullName()<<") ["
                        <<bbGetFullName()<<"]"<<std::endl);
@@ -335,6 +320,7 @@ namespace bbtk
       {                
        if (! i->second->GetCopyConstruct() ) continue;
        std::string input = i->second->GetName();
+       bbtkDebugMessage("Kernel",2,"* Copying input "<<input<<std::endl);
        this->bbSetInput(input, from.bbGetInput(input) );
       }                                                                        
     // copies the output values
@@ -345,6 +331,7 @@ namespace bbtk
       {                                                        
        if (! o->second->GetCopyConstruct() ) continue;
        std::string output = o->second->GetName();
+       bbtkDebugMessage("Kernel",2,"* Copying output "<<output<<std::endl);
        this->bbSetOutput(output, from.bbGetOutput(output) );
       }
 
@@ -359,7 +346,7 @@ namespace bbtk
   bool BlackBox::bbCanReact() const 
   { 
     return ( bbGlobalGetSomeBoxExecuting() 
-#ifdef _USE_WXWIDGETS_
+#ifdef USE_WXWIDGETS
             || Wx::IsSomeWindowAlive() 
 #endif
             ); 
@@ -417,90 +404,199 @@ namespace bbtk
   }
   //=========================================================================
 
+
+
+
   //=========================================================================
-  ///  Signals that the BlackBox has been modified
-  void BlackBox::bbSetModifiedStatus(BlackBoxInputConnector* c)
+  void BlackBox::bbAddOutputObserver(const std::string& output, 
+                                  OutputChangeCallbackType f)
   {
-    bbtkDebugMessage("modified",1,
-                    "==> BlackBox::bbSetModifiedStatus("<<c<<") ["
+    bbGetOutputConnector(output).AddChangeObserver(f);
+  }  
+  //=========================================================================
+
+  //=========================================================================
+  void BlackBox::bbRemoveOutputObserver(const std::string& output_name, 
+                                     OutputChangeCallbackType f)
+  {
+    bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
+  }
+  //=========================================================================
+
+
+  /*
+  //=========================================================================
+  ///  Sets the ChangeTime of input 
+  void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c, 
+                                     const ChangeTime& t)
+  {
+    bbtkDebugMessage("change",1,
+                    "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
                     <<bbGetFullName()<<"]"<<std::endl);
     
-    if ( (c==bbGetInputConnectorMap().find("WinHide")->second) )
-      //        && (bbCanReact()))
+    // If new time is greater than old one
+    if ( c->SetChangeTime(t) ) 
       {
-       bbtkDebugMessage("modified",2,
-                        "-> Hide triggered by WinHide input change"
-                        <<std::endl);
-       this->bbHideWindow();
-       this->bbSetStatus(MODIFIED); 
-       return;
+       bool was_up_to_date = bbIsUpToDate();
+       // If new time is greater than the old max time of inputs
+       if ( mMaxInputChangeTime.Set(t) ) 
+         {
+           // If the box turned out-of-date
+           if ( was_up_to_date && bbIsOutOfDate() )
+             {
+               // 
+               if ( ( bbBoxProcessModeIsReactive()  ||
+                      (c==bbGetInputConnectorMap().find("BoxExecute")->second))
+                    && (bbCanReact() ) )
+                 {
+                   bbtkDebugMessage("change",2,
+                                    "an input of "
+                                    <<bbGetFullName()
+                                    <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
+                                    <<std::endl);
+                   bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
+                 }
+               // Have to propagate the modification to aval boxes
+               OutputConnectorMapType::iterator i;
+               for (i = bbGetOutputConnectorMap().begin();
+                    i != bbGetOutputConnectorMap().end();
+                    ++i)
+                 {
+                   i->second->SetChangeTime(t);
+                 }
+               // update the MinOutputChangeTime
+               mMinOutputChangeTime.Set(t);
+             }
+         }
       }
-    if ( (c==bbGetInputConnectorMap().find("WinClose")->second) )
-      //        && (bbCanReact()))
+  }
+  //=========================================================================
+
+ //=========================================================================
+  ///  Sets the ChangeTime of output 
+  void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c, 
+                                      const ChangeTime& t)
+  {
+    bbtkDebugMessage("change",1,
+                    "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
+                    <<bbGetFullName()<<"]"<<std::endl);
+    
+    //ChangeTime old = 
+    c->SetChangeTime(t);
+    // c->GetChangeTime() = t;
+    //    bbUpdateMinOutputChangeTime(t);
+    // propagate
+    
+  }
+  //=========================================================================
+  */
+
+  /*
+  //=========================================================================
+  void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
+  {    
+
+    
+    if ( t > mMaxInputChangeTime ) 
+      {
+       mMaxInputChangeTime = t;
+       if ( mMinOutputChangeTime > mMaxInputChangeTime )
+         {
+           
+         }
+      }
+    
+  }
+  //=========================================================================
+
+  //=========================================================================
+  void bbUpdateMinOutputChangeTime(const ChangeTime& t)
+  {
+    ChangeTime old = mMinOutputChangeTime;
+    mMinOutputChangeTime = MAXLONG;
+    OutputConnectorMapType::iterator i;
+    for (i = bbGetOutputConnectorMap.begin();
+        i != bbGetOutputConnectorMap.end();
+        ++i)
+      {
+       if (i->second->GetChangeTime() < mMinOutputChangeTime)
+         mMinOutputChangeTime = i->second->GetChangeTime();
+      }
+    if ( mMinOutputChangeTime < old )
       {
-       bbtkDebugMessage("modified",2,
-                        "-> Close triggered by WinClose input change"
-                        <<std::endl);
-       this->bbHideWindow();
-       this->bbSetStatus(MODIFIED); 
-       return;
       }
+   
+  }
+  //=========================================================================
+  */
+
+  //=========================================================================
+  /// Signals that the BlackBox has been modified through 
+  /// the input connector c
+  /// and propagates it downward
+  /// ** NOT USER INTENDED **
+  void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
+                                        IOStatus s)
+  {
+    bbtkDebugMessageInc("change",5,
+                       "=> BlackBox::bbSetStatusAndPropagate(input,"
+                       <<GetIOStatusString(s)<<") ["
+                       <<bbGetFullName()<<"]"<<std::endl);
+
+    if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
+    c->SetStatus(s);
+    OutputConnectorMapType::const_iterator o;  
+    for ( o = bbGetOutputConnectorMap().begin(); 
+         o != bbGetOutputConnectorMap().end(); ++o )                   
+      {                                                                        
+       if (o->second->GetStatus()==UPTODATE) 
+         {
+           o->second->SetStatus(OUTOFDATE);
+           o->second->SignalChange(GetThisPointer<BlackBox>(),o->first); 
+         }
+      }                                                                        
     
     if ( ( bbBoxProcessModeIsReactive()  ||
           (c==bbGetInputConnectorMap().find("BoxExecute")->second))
         && (bbCanReact() ) )
       {
-       bbtkDebugMessage("modified",2,
+       bbtkDebugMessage("change",2,
                         "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
-       this->bbSetStatus(MODIFIED); 
         bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
-      }
-    else if ( bbGetStatus() == MODIFIED ) //! this->bbIsUptodate()) 
-      { 
-       bbtkDebugMessage("modified",2,"-> Already modified"<<std::endl);
-       return;
-      }
-    else 
-      {
-       bbtkDebugMessage("modified",2,"-> Status set to modified"<<std::endl);
-       this->bbSetStatus(MODIFIED); 
-      }
-    this->bbSignalOutputModification(false);
-
-    /* 
-  bbtkDebugMessageDec("process",5,
-                       "<= BlackBox::bbSetModifiedStatus("<<c<<") ["
+      }    
+    bbtkDebugMessageInc("change",5,
+                       "<= BlackBox::bbSetStatusAndPropagate(input) ["
                        <<bbGetFullName()<<"]"<<std::endl);
-    */
-  }  
+  }
   //=========================================================================
 
+
   //=========================================================================  
   void BlackBox::bbSignalOutputModification(bool reaction)
   {
-    bbtkDebugMessageInc("process",5,
-                       "=> BlackBox::bbSignalOutputModification() ["
+    bbtkDebugMessageInc("change",5,
+                       "=> BlackBox::bbSignalOutputModification("
+                       <<reaction<<") ["
                        <<bbGetFullName()<<"]"<<std::endl);
     
-    OutputConnectorMapType::iterator change = bbGetOutputConnectorMap().end();
     OutputConnectorMapType::iterator i;
     for ( i  = bbGetOutputConnectorMap().begin(); 
-         i != bbGetOutputConnectorMap().end(); ++i) {
-      /*     if ( i->first == "BoxChange" ) 
-       {
-         change = i;
-         continue;
-       }
-      */
-      i->second->SetModifiedStatus();
-    } 
-    //    if (change != bbGetOutputConnectorMap().end()) 
-    // change->second->SetModifiedStatus();
+         i != bbGetOutputConnectorMap().end(); ++i) 
+      {
+       //      std::cout << "Stat = "
+       //<<GetIOStatusString(i->second->GetStatus())
+       //                <<std::endl;
+       // LG : CANNOT SIGNAL ONLY WHEN UPTODATE 
+       // See bbtkSampleOutputObserver
+       //      if (i->second->GetStatus()==UPTODATE) 
+       //        {
+           i->second->SignalChange(GetThisPointer<BlackBox>(),i->first); 
+           //    }
+      } 
 
     if (reaction) bbGlobalProcessExecutionList();
 
-    bbtkDebugMessageDec("process",5,
+    bbtkDebugMessageDec("change",5,
                        "<= BlackBox::bbSignalOutputModification() ["
                        <<bbGetFullName()<<"]"<<std::endl);
     
@@ -508,46 +604,54 @@ namespace bbtk
   //=========================================================================   
   //=========================================================================  
   void BlackBox::bbSignalOutputModification(const std::string& output,
-       bool reaction)
+                                           bool reaction)
   {
-    bbtkDebugMessageInc("process",5,
+    bbtkDebugMessageInc("change",5,
                        "=> BlackBox::bbSignalOutputModification("
-                       <<output<<") ["
+                       <<output<<","<<reaction<<") ["
                        <<bbGetFullName()<<"]"<<std::endl);
     
-    OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(output);
+    OutputConnectorMapType::iterator i = 
+      bbGetOutputConnectorMap().find(output);
+
+
     if ( i == bbGetOutputConnectorMap().end() ) 
        {
          bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
        }
-    i->second->SetModifiedStatus();
-    // Has to notify the output "BoxChange" also
-    if (output != "BoxChange") 
-      {
-       i = bbGetOutputConnectorMap().find("BoxChange");
-       if ( i != bbGetOutputConnectorMap().end() 
+
+    //    if (i->second->GetStatus()==UPTODATE) 
+    //      {
+       i->second->SignalChange(GetThisPointer<BlackBox>(),i->first); 
+       // Has to notify the output "BoxChange" also
+       if (output != "BoxChange"
          {
-           i->second->SetModifiedStatus();
+           i = bbGetOutputConnectorMap().find("BoxChange");
+           if ( i != bbGetOutputConnectorMap().end() ) 
+             {
+               i->second->SignalChange(GetThisPointer<BlackBox>(),i->first); 
+             }
          }
-      }
-  if (reaction) bbGlobalProcessExecutionList();
-
-  bbtkDebugMessageDec("process",5,
-                      "<= BlackBox::bbSignalOutputModification("
-                      <<output<<") ["
-                      <<bbGetFullName()<<"]"<<std::endl);
+       if (reaction) bbGlobalProcessExecutionList();
+       //      }
 
+    bbtkDebugMessageDec("change",5,
+                       "<= BlackBox::bbSignalOutputModification("
+                       <<output<<") ["
+                       <<bbGetFullName()<<"]"<<std::endl);
+    
   }  
   //=========================================================================   
   //=========================================================================  
   void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
        bool reaction)
   {
-    bbtkDebugMessageInc("process",5,
+    bbtkDebugMessageInc("change",5,
                        "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
                        <<bbGetFullName()<<"]"<<std::endl);
     OutputConnectorMapType::iterator i;
     std::vector<std::string>::const_iterator o;
+    bool changed = false;
     for (o=output.begin();o!=output.end();++o) 
       {
        // the output "BoxChange" must be signaled **AFTER** all others
@@ -558,28 +662,155 @@ namespace bbtk
          {
            bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
          }
-       i->second->SetModifiedStatus();
+
+       //      if (i->second->GetStatus()==UPTODATE)
+       //        {
+           i->second->SignalChange(GetThisPointer<BlackBox>(),i->first); 
+           changed = true;
+           //  }
       }
     // Has to notify the output "BoxChange" also
     i = bbGetOutputConnectorMap().find("BoxChange");
-    if ( i != bbGetOutputConnectorMap().end() 
+    if ( changed && (i != bbGetOutputConnectorMap().end())
       {
-       i->second->SetModifiedStatus();
+       // if (i->second->GetStatus()==UPTODATE) 
+       //        {
+           i->second->SignalChange(GetThisPointer<BlackBox>(),i->first); 
+           if (reaction) bbGlobalProcessExecutionList();
+           //  }
       }
-  if (reaction) bbGlobalProcessExecutionList();
 
-   bbtkDebugMessageDec("process",5,
-                      "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
+    bbtkDebugMessageDec("change",5,
+                       "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
                        <<bbGetFullName()<<"]"<<std::endl);
 
   }  
   //=========================================================================   
 
+
+
+
+
+
+
+  //=========================================================================
+  /// Main processing method of the box.
+  void BlackBox::bbExecute(bool force)
+  {
+    bbtkDebugMessageInc("process",2,
+                       "=> BlackBox::bbExecute("<<(int)force<<") ["
+                       <<bbGetFullName()<<"]"<<std::endl);
+    // If already executing : return
+    /*
+    if (bbGetExecuting()) 
+      {
+       bbtkDebugMessage("process",2,
+                        " -> already executing : abort"<<std::endl);
+       return;
+      }
+    */
+
+    // If execution frozen : return
+    if (bbGlobalGetFreezeExecution()) 
+      {
+       bbtkDebugMessage("process",2,
+                        " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
+      }
+
+    BBTK_BUSY_CURSOR;
+
+    // If force is true then update is triggered even if the box is UPTODATE
+    //    if (force) bbSetModifiedStatus();
+
+    // Calls the main recursive execution method 
+    bbRecursiveExecute(Connection::Pointer());
+
+    bbtkDebugMessageDec("process",2,
+                       "<= BlackBox::bbExecute() ["
+                       <<bbGetFullName()<<"]"<<std::endl);
+  }
+  //=========================================================================
+
+
+  //=========================================================================
+  /// Main recursive processing method of the box.
+  void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
+  {
+    bbtkDebugMessageInc("process",3,
+                       "=> BlackBox::bbRecursiveExecute("
+                       <<(caller?caller->GetFullName():"0")<<") ["
+                       <<bbGetFullName()<<"]"<<std::endl);
+
+    // If already executing : return
+    if (bbGetExecuting()) 
+      {
+       bbtkDebugMessage("process",3,
+                        " -> already executing : abort"<<std::endl);
+       return; 
+      }
+
+    bbSetExecuting(true);
+    bool wasExecuting = bbGlobalGetSomeBoxExecuting();
+    bbGlobalSetSomeBoxExecuting(true);
+
+    // Updates its inputs
+    IOStatus s = bbUpdateInputs();
+    
+    if ( (s != UPTODATE) ||
+        bbBoxProcessModeIsAlways() )
+      {
+       // Displays the window (WxBlackbox)
+       //      bbShowWindow(caller);
+
+       // Actual processing (virtual)
+       this->bbProcess();
+       
+       
+       // Update the I/O statuses
+       bbComputePostProcessStatus();
+      }
+    else 
+      {
+       // Test output status...
+       OutputConnectorMapType::iterator o;
+       for ( o = bbGetOutputConnectorMap().begin(); 
+             o!= bbGetOutputConnectorMap().end(); ++o) 
+         {
+           if (o->second->GetStatus() != UPTODATE)
+             {
+               bbtkWarning("BlackBox::bbRecursiveExecute ["
+                           <<bbGetFullName()
+                           <<"] : all inputs are Up-to-date but output '"
+                           <<o->first<<"' is Out-of-date ???");
+             }
+         }
+       
+        bbtkDebugMessage("process",3," -> Up-to-date : nothing to do"
+                        <<std::endl);
+      }
+
+    bbtkDebugMessage("process",3,
+            "<= BlackBox::bbRecursiveExecute() ["
+            <<bbGetFullName()<<"]"<<std::endl);
+
+    bbSetExecuting(false);
+    bbGlobalSetSomeBoxExecuting(wasExecuting);
+
+    return; 
+
+  }
+  //=========================================================================
+  
+   
+
+
+
   //=========================================================================
   /// Updates the BlackBox inputs
-  /// \returns UPTODATE if all inputs are in UPTODATE status after update
-  ///          else MODIFIED 
-  IOStatus BlackBox::bbUpdateInputs(bool excludeParent)
+  /// Calls RecursiveExecute on all BlackBoxInputConnector
+  /// \returns The maximum of final IOStatus after each input update
+  IOStatus BlackBox::bbUpdateInputs()
   {
     bbtkDebugMessageInc("process",4,
                        "=> BlackBox::bbUpdateInputs() ["
@@ -592,28 +823,85 @@ namespace bbtk
     for ( i = bbGetInputConnectorMap().begin(); 
          i!= bbGetInputConnectorMap().end(); ++i) 
       {
-       if (excludeParent && (i->first=="WinParent")) continue;
-       if (i->first=="WinHide") continue;
+       //      if (i->first=="WinHide") continue;
        // If input type is Void : no recurse
        //if (  bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo() 
        //      == typeid(Void) ) 
        //  continue;
-
-       IOStatus t = i->second->BackwardUpdate();
-       if (t==MODIFIED) s = MODIFIED;
+       bbtkDebugMessageDec("change",2,
+                           bbGetName()<<"."<<i->first
+                           <<" ["<<i->second<<"] "
+                           <<" status before update = '"
+                           <<GetIOStatusString(i->second->GetStatus())
+                           <<"'"<<std::endl);
+       i->second->RecursiveExecute();
+       IOStatus t = i->second->GetStatus();
+       if (t > s) s = t;
+       bbtkDebugMessageDec("change",2,
+                           bbGetName()<<"."<<i->first
+                           <<" ["<<i->second<<"] "
+                           <<" status before process = '"
+                           <<GetIOStatusString(i->second->GetStatus())
+                           <<"'"<<std::endl);
       }
     
-   bbtkDebugMessageDec("process",4,
+    bbtkDebugMessageDec("process",4,
                        "<= BlackBox::bbUpdateInputs() ["
                        <<bbGetFullName()<<"]"
                        <<std::endl);   
-
-
+    
+    
     return s;
   }
   //=========================================================================
 
+  //==================================================================
+  /// Computes the final IOStatus of inputs and outputs after processing
+  void BlackBox::bbComputePostProcessStatus()
+  {
+    bbtkDebugMessageInc("process",4,
+                       "=> BlackBox::bbComputePostProcessStatus() ["
+                       <<bbGetFullName()<<"]"
+                       <<std::endl);   
+
+    IOStatus new_output_status = UPTODATE;
+    if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
+
+    // Update the input statuses
+    InputConnectorMapType::iterator i;
+    for ( i = bbGetInputConnectorMap().begin(); 
+         i!= bbGetInputConnectorMap().end(); ++i) 
+      {
+       IOStatus t = i->second->GetStatus();
+       if (t == OUTOFDATE) new_output_status = OUTOFDATE;
+       // A previously MODIFIED status turns to UPTODATE
+       if (t==MODIFIED) i->second->SetStatus(UPTODATE);
+       bbtkDebugMessage("change",2,
+                        bbGetName()<<"."<<i->first<<" : "
+                        << GetIOStatusString(t) << " -> "
+                        << GetIOStatusString(i->second->GetStatus())
+                        << std::endl);
+      }
+       bbtkDebugMessage("change",2,
+                        bbGetName()<<" new output status : "
+                        << GetIOStatusString(new_output_status)
+                        <<std::endl);
+    // Update the output statuses
+    OutputConnectorMapType::iterator o;
+    for ( o = bbGetOutputConnectorMap().begin(); 
+         o!= bbGetOutputConnectorMap().end(); ++o) 
+      {
+       o->second->SetStatus(new_output_status);
+      }
+
+    bbtkDebugMessageInc("process",4,
+                       "<= BlackBox::bbComputePostProcessStatus() ["
+                       <<bbGetFullName()<<"]"
+                       <<std::endl);   
+
+  }
+  //==================================================================
+
   //=========================================================================
   /// Connects the input <name> to the connection c
   void BlackBox::bbConnectInput( const std::string& name, Connection* c)
@@ -631,13 +919,14 @@ namespace bbtk
        bbtkError("no input called '"<<name<<"'");
       }
     i->second->SetConnection(c);
+    // The input *MUST* be set OUTOFDATE to update its input on next execution
+    bbSetStatusAndPropagate(i->second,OUTOFDATE);
     
     bbtkDebugMessage("connection",2,
                        "<== BlackBox::bbConnectInput(\""
                        <<name<<"\","<<c->GetFullName()<<") ["
                        <<bbGetFullName()<<"]"
                        <<std::endl);       
-    //  bbSetModifiedStatus();
 
   }
   //=========================================================================
@@ -844,11 +1133,11 @@ namespace bbtk
     std::string ss("<");
     std::string::size_type pos = 0;
     pos = s.find(ss,0);
-    char* cr = "[";
+    std::string cr("[");
     while ( pos != std::string::npos )
       {
        //      std::cout << "*** find one "<<std::endl;
-       s.replace(pos,1,cr,1);
+       s.replace(pos,1,cr.c_str(),1);
        pos = s.find(ss, pos);
       } 
     ss = ">";
@@ -858,7 +1147,7 @@ namespace bbtk
     while ( pos != std::string::npos )
       {
        //      std::cout << "*** find one "<<std::endl;
-       s.replace(pos,1,cr,1);
+       s.replace(pos,1,cr.c_str(),1);
        pos = s.find(ss, pos);
       } 
     ss = ",";
@@ -868,7 +1157,7 @@ namespace bbtk
     while ( pos != std::string::npos )
       {
        //      std::cout << "*** find one "<<std::endl;
-       s.replace(pos,1,cr,1);
+       s.replace(pos,1,cr.c_str(),1);
        pos = s.find(ss, pos);
       }     //    std::cout << "AFTER=["<<s<<"]"<<std::endl;
   }
@@ -1008,17 +1297,30 @@ namespace bbtk
       {
        bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
       }
+    /*
+    if (bbIsUpToDate())
+      {
+       bbtkMessage("Help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
+                   <<mMinOutputChangeTime<<"]"<<std::endl);
+      }
+    else 
+      {
+       bbtkMessage("Help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
+                   <<mMinOutputChangeTime<<"]"<<std::endl);
+      }
+    */
     //    bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
     //    bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
 
     std::vector<std::string> iname;
     std::vector<std::string> ivalue;
     std::vector<std::string> iconn;
+    std::vector<std::string> istatus;
 
     InputConnectorMapType::iterator i;
     unsigned int namelmax = 0;
     unsigned int valuelmax = 0;
-    unsigned int connlmax = 0;
+    //   unsigned int connlmax = 0;
     for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) 
       {
        iname.push_back(i->first);
@@ -1033,11 +1335,13 @@ namespace bbtk
          s += con->GetOriginalBlackBoxFromOutput();
        }  // if con
        iconn.push_back(s);
+       istatus.push_back(GetIOStatusString(i->second->GetStatus()));
       }
     OutputConnectorMapType::iterator o;
     std::vector<std::string> oname;
     std::vector<std::string> ovalue;
     std::vector<std::vector<std::string> > oconn;
+    std::vector<std::string> ostatus;
     for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o ) 
       {
        oname.push_back(o->first);
@@ -1057,6 +1361,7 @@ namespace bbtk
            ss.push_back(s);
        }  // if con
        oconn.push_back(ss);
+       ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
       }
 
     if (iname.size()) 
@@ -1064,10 +1369,10 @@ namespace bbtk
     else 
       bbtkMessage("Help",1," * No inputs"<<std::endl);
 
-    std::vector<std::string>::iterator i1,i2,i3;
-    for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin();
-        i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end();
-        ++i1,++i2,++i3)
+    std::vector<std::string>::iterator i1,i2,i3,i4;
+    for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
+        i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
+        ++i1,++i2,++i3,++i4)
       {
        std::string name(*i1);
        name += "'";
@@ -1076,9 +1381,11 @@ namespace bbtk
        value += "'";
        value.append(1+valuelmax-value.size(),' ');
        if (i3->size()) 
-         bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<" <-- '"<<*i3<<"'"<<std::endl);
+         bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<" <-- '"
+                     <<*i3<<"'");
        else 
-         bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<std::endl);
+         bbtkMessage("Help",1,"    '"<<name<<" = '"<<value);
+       bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
       }
 
     if (oname.size()) 
@@ -1086,11 +1393,11 @@ namespace bbtk
     else 
       bbtkMessage("Help",1," * No outputs"<<std::endl);
 
-    std::vector<std::vector<std::string> >::iterator i4;
+    std::vector<std::vector<std::string> >::iterator i5;
 
-    for (i1=oname.begin(),i2=ovalue.begin(),i4=oconn.begin();
-        i1!=oname.end(),i2!=ovalue.end(),i4!=oconn.end();
-        ++i1,++i2,++i4)
+    for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
+        i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
+        ++i1,++i2,++i4,++i5)
       {
        std::string name(*i1);
        name += "'";
@@ -1098,38 +1405,55 @@ namespace bbtk
        std::string value(*i2);
        value += "'";
        value.append(1+valuelmax-value.size(),' ');
-       if (!(*i4).size())
-         bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<std::endl);
+       if (!(*i5).size())
+         bbtkMessage("Help",1,"    '"<<name<<" = '"<<value);
        else 
          {
            std::string pref = "    '"+name+" = '"+value;
-           for (i3=i4->begin();i3!=i4->end();++i3)
+           for (i3=i5->begin();i3!=i5->end();++i3)
              {
-               bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'"<<std::endl);
+               bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'");
                pref.replace(0,pref.size(),pref.size(),' ');
              }
          }
+       bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
       }
 
    }
   //=========================================================================
 
+  static bool bbmgGlobalProcessingExecutionList = false;
 
   //=========================================================================
    void BlackBox::bbGlobalProcessExecutionList()
    {   
      bbtkDebugMessageInc("process",3,
                         "=> BlackBox::bbGlobalProcessExecutionList()"
-                        <<std::endl);     
-     
-     std::set<BlackBox::Pointer>::iterator i;
-     for (i=bbmgExecutionList.begin();
-         i!=bbmgExecutionList.end();
-         ++i)
+                        <<std::endl);    
+     if (bbmgGlobalProcessingExecutionList) 
        {
-        bbtkDebugMessage("process",4,
-                         " -> Executing "<<(*i)->bbGetFullName()<<std::endl);
-        (*i)->bbExecute(true);
+        bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
+        return;
+       }
+     bbmgGlobalProcessingExecutionList = true;
+
+     std::set<BlackBox::WeakPointer>::iterator i; 
+     while (bbmgExecutionList.size()>0)
+       {
+        i = bbmgExecutionList.begin();
+        BlackBox::WeakPointer p = *i;
+        bbmgExecutionList.erase(i);
+        if (p.lock())
+          {
+            bbtkDebugMessage("process",4,
+                             " -> Executing "<<
+                             p.lock()->bbGetFullName()<<std::endl);
+            p.lock()->bbExecute(true);
+          }
+        else 
+          {
+            bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
+          }
        }
      
      bbmgExecutionList.clear();
@@ -1137,6 +1461,7 @@ namespace bbtk
                         "<= BlackBox::bbGlobalProcessExecutionList()"
                         <<std::endl);     
      
+     bbmgGlobalProcessingExecutionList = false;
      
    }
   //=========================================================================
@@ -1162,9 +1487,14 @@ namespace bbtk
        }
 
   void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
-       {  
-               bbmgExecutionList.insert(b); 
-       } 
+  {  
+    bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
+    if (bbmgGlobalProcessingExecutionList) 
+      {
+       bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
+      }
+    bbmgExecutionList.insert(b); 
+  } 
 
 
    //=========================================================================