-/*=========================================================================
-
+/*=========================================================================
Program: bbtk
Module: $RCSfile: bbtkBlackBox.h,v $
Language: C++
- Date: $Date: 2008/01/22 15:02:00 $
- Version: $Revision: 1.1 $
-
- 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.
-
+ Date: $Date: 2008/12/08 12:53:47 $
+ Version: $Revision: 1.17 $
=========================================================================*/
+/* ---------------------------------------------------------------------
+
+* 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
#ifndef __bbtkBlackBox_h__
#define __bbtkBlackBox_h__
+#include "bbtkSystem.h"
#include "bbtkBlackBoxDescriptor.h"
-//#include "bbtkConnection.h"
#include "bbtkBlackBoxInputConnector.h"
-#include "bbtkBlackBoxOutputConnector.h"
+//#include "bbtkBlackBoxOutputConnector.h"
#include <set>
+// Signal/slot mechanism for output change events
+#include <boost/signal.hpp>
+#include <boost/bind.hpp>
+
namespace bbtk
{
struct Void { Void(int = 0) {} };
class Factory;
+ class Connection;
+ class BlackBoxOutputConnector;
- class BBTK_EXPORT BlackBox
+ class BBTK_EXPORT BlackBox : public Object
{
-
-
+ BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
public:
//==================================================================
// INTERFACE
//==================================================================
- /// The type of pointer on a BlackBox
- typedef BlackBox* Pointer;
-
+ typedef boost::signals::trackable OutputChangeObserverType;
+ typedef boost::signal<void (bbtk::BlackBox::Pointer,
+ const std::string&,
+ IOStatus)> OutputChangeSignalType;
+ typedef OutputChangeSignalType::slot_function_type
+ OutputChangeCallbackType;
+
/// The type of map of output connector pointers
typedef std::map<std::string, BlackBoxOutputConnector*>
OutputConnectorMapType;
InputConnectorMapType;
/// Returns the pointer on the descriptor of the box
- virtual BlackBoxDescriptor* bbGetDescriptor() const = 0;
+ virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
/// Returns a pointer on a clone of the box with name <name>
- virtual BlackBox* bbClone(const std::string& name) = 0;
+ virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
- /// Destruction method of a black box
- virtual void bbDelete();
/// User overloadable destruction method of a black box
virtual void bbUserDelete();
virtual std::string bbGetFullName() const;
/// Returns the name with the name of the parent prepended if any
- std::string bbGetNameWithParent() const;
+ virtual std::string bbGetNameWithParent() const;
- /// Sets the parent of the BlackBox
- void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
/// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
- BlackBox::Pointer bbGetParent() const { return bbmParent; }
+ BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
/// Main processing method of the box.
virtual void bbExecute(bool force = false);
- /// Signals that the BlackBox has been modified through the input connector c
- /// and propagates it downward
- virtual void bbSetModifiedStatus(BlackBoxInputConnector* c = 0);
+
+ /// The type of callback function when an output changes
+ // typedef BlackBoxOutputConnector::ChangeCallbackType OutputChangeCallbackType;
+
+ /// Adds the function f to the list of functions to call when
+ /// the output changes.
+ /// f is of type ChangeCallbackType which is basically:
+ /// void (*ChangeCallbackType)(BlackBoxOutputConnector*)
+ /// To pass a member function 'f' of an instance 'c' of a class 'C'
+ /// as callback you have to 'bind' it, i.e. call:
+ /// AddChangeObserver ( "Out", boost::bind( &C::f , c, _1 ) );
+ void AddChangeObserver(const std::string& output_name,
+ OutputChangeCallbackType f);
+
+ /// Removes the function f from the list of functions to call when
+ /// the output changes (TO WRITE)
+ void RemoveChangeObserver(const std::string& output_name,
+ OutputChangeCallbackType f);
+
+
/// Signals that the BlackBox outputs have been modified
- /// without marking the box as MODIFIED because its output state is ok.
+ /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
/// This method should be used by widgets in response
/// to user interaction when **ALL** outputs have been modified
- /// (after the outputs has been updated !)
+ /// (after the outputs has been updated !).
+ /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
+ /// ** USER INTENDED **
virtual void bbSignalOutputModification(bool reaction = true);
- /// Signals that the BlackBox output "output_name" have been modified
- /// without marking the box as MODIFIED because its output state is ok.
+ /// Signals that the BlackBox output "output_name" has been modified
+ /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
/// This method should be used by widgets in response to user interaction
/// only when **ONE** output has been modified
/// (after the output has been updated !)
+ /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
+ /// ** USER INTENDED **
virtual void bbSignalOutputModification( const std::string& output_name,
-bool reaction = true);
- /// Signals that the BlackBox vector of outputs "output_name"
- /// have been modified
- /// without marking the box as MODIFIED because its output state is ok.
+ bool reaction = true);
+ /// Signals that the BlackBox vector of outputs "output_name"
+ /// have been modified.
+ /// Should be used when more than ONE output is modified but not ALL
+ /// (optimization issue).
+ /// (without marking the box as MODIFIED because its output state is ok).
/// This method should be used by widgets in response to user interaction
/// When more than one output has been changed but not all
/// (after the outputs have been updated of course!)
- virtual void bbSignalOutputModification( const std::vector<std::string>& output_name,
-bool reaction = true);
+ /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
+ /// ** USER INTENDED **
+ virtual void bbSignalOutputModification( const std::vector<std::string>&
+ output_name,
+ bool reaction = true);
/// Gets the status of the box
- virtual const IOStatus& bbGetStatus() const { return bbmStatus; }
+ // virtual const IOStatus& bbGetStatus() const { return bbmStatus; }
/// Returns true iff the BlackBox has an input of name label
virtual Data bbGetOutput( const std::string &name ) = 0;
/// Sets the data of the input called <name>.
- /// If setModified is false then does not call bbSetModifiedStatus()
+ /// If update_time is false then does not update ChangeTime of input
virtual void bbSetInput( const std::string &name, Data data,
- bool setModified = true ) = 0;
+ bool update_time = true ) = 0;
virtual void bbBruteForceSetInputPointer( const std::string &name,
void* data,
- bool setModified = true) =0;
+ bool update_time = true) =0;
/// Sets the data of the output called <name>
virtual void bbSetOutput( const std::string &name, Data data) = 0;
- /// Connects the input <name> to the connection c
- virtual void bbConnectInput( const std::string& name, Connection* c);
- /// Connects the output <name> to the connection c
- virtual void bbConnectOutput( const std::string& name, Connection* c);
-
- /// Disconnects the input <name> from the connection c
- virtual void bbDisconnectInput( const std::string& name, Connection* c);
- /// Disconnects the output <name> from the connection c
- virtual void bbDisconnectOutput( const std::string& name, Connection* c);
/// Returns the input connectors map
InputConnectorMapType& bbGetInputConnectorMap()
/// Returns the output connectors map (const)
const OutputConnectorMapType& bbGetOutputConnectorMap() const
{ return mOutputConnectorMap; }
+
+ /// Returns the input connector
+ BlackBoxInputConnector& bbGetInputConnector(const std::string& n)
+ { return *(mInputConnectorMap.find(n)->second); }
+ /// Returns the output connector
+ BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n)
+ { return *(mOutputConnectorMap.find(n)->second); }
+ /// Returns the input connector (const)
+ const BlackBoxInputConnector& bbGetInputConnector(const std::string& n) const
+ { return *(mInputConnectorMap.find(n)->second); }
+ /// Returns the output connector (const)
+ const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const
+ { return *(mOutputConnectorMap.find(n)->second); }
+
+
/// Prints the Help on the BlackBox type
virtual void bbGetHelp(bool full=true) const;
- //==================================================================
+ // Returns true iff the box is up-to-date
+ // (ChangeTime of inputs are all lower strictly to ChangeTime of outputs -
+ // i.e. max(inputs)<=min(outputs) )
+ // bool bbIsUpToDate() { return mMaxInputChangeTime < mMinOutputChangeTime; }
+ // Returns true iff the box is out-of-date
+ // (At least one ChangeTime of an input is greater than one ChangeTime
+ // of an output - i.e. max(inputs)>min(outputs))
+ // == !IsUpToDate()
+ // bool bbIsOutOfDate() { return mMaxInputChangeTime >= mMinOutputChangeTime; }
+
+ //==================================================================
// Common inputs / outputs to all boxes
/// Returns the value of the input "BoxProcessMode"
std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
/// Returns the value of the output "Change"
Void bbGetOutputBoxChange() { return Void(); }
/// Sets the value of the output "Change" : signal a modification
- void bbSetOutputBoxChange(Void = 0) { bbSetModifiedStatus(); }
+ void bbSetOutputBoxChange(Void = 0) { } //bbSetModifiedStatus(); }
//==================================================================
/// (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
/// If relative_link is true then creates relative hrefs
virtual void bbWriteDotFileBlackBox(FILE *ff,
- BlackBox *parentblackbox,
+ BlackBox::Pointer parentblackbox,
int detail, int level,
bool instanceOrtype,
bool relative_link );
int detail, int level);
- virtual void bbShowRelations(BlackBox *parentblackbox,
+ virtual void bbShowRelations(BlackBox::Pointer parentblackbox,
int detail, int level
);
std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
- virtual BlackBox *bbFindBlackBox(const std::string &blackboxname) { return NULL;}
+ virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname)
+ { return BlackBox::Pointer();}
+
+ virtual void Check(bool recursive = true);
+
+ virtual void bbUserOnShow() { }
+ void bbUserOnShowWidget(std::string nameInput);
protected:
//==================================================================
BlackBox(const std::string &name);
/// Constructor from an existing box (copy) with a new name
BlackBox(BlackBox& from, const std::string &name);
- /// Destructor
- virtual ~BlackBox();
//==================================================================
//==================================================================
- /// Sets the status of the box
- void bbSetStatus( IOStatus t) { bbmStatus = t; }
+ /// Signals that the input whose connector is c has changed
+ /// and propagates the info downward
+ /// ** NOT USER INTENDED **
+ virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* c,
+ IOStatus s);
+ /// Signals that the output whose connector is c has changed
+ /// and propagates the info downward
+ /// ** NOT USER INTENDED **
+ virtual void bbSetStatusAndPropagate(BlackBoxOutputConnector* c,
+ IOStatus s);
+ //==================================================================
+
+ private:
//==================================================================
+ friend class Connection;
+ friend class ComplexBlackBox;
+
+ /// Sets the parent of the BlackBox
+ void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
-
+ /// Connects the input <name> to the connection c
+ virtual void bbConnectInput( const std::string& name,
+ Connection* c);
+ /// Connects the output <name> to the connection c
+ virtual void bbConnectOutput( const std::string& name,
+ Connection* c);
+ /// Disconnects the input <name> from the connection c
+ virtual void bbDisconnectInput( const std::string& name,
+ Connection* c);
+ /// Disconnects the output <name> from the connection c
+ virtual void bbDisconnectOutput( const std::string& name,
+ Connection* c);
+
+ //==================================================================
+ protected:
/// @name Pipeline processing methods
- /// Methods which participate to (forward or backward) pipeline processing.
- /// Some are pure virtual and prepare particular update mechanism which are implemented by descendents (e.g. ForwardUpdate and UpdateChildren are made for WxContainerBlackBox particular update mechanism which must recurse a piece of the pipeline top-down).
+ /// Methods which participate to pipeline processing.
+ /// Some are pure virtual and prepare particular update mechanism which are implemented by descendents
/// The main method is bbBackwardUpdate which is called by bbExecute and implemented in UserBlackBox and ComplexBlackBox.
///
//@{
+
//==================================================================
/// Recursive pipeline processing in backward direction
- /// (recursion is in backward direction however execution always goes forward).
- /// Pure virtual; defined in UserBlackBox and ComplexBlackBox
+ /// (recursion is in backward direction however execution always
+ /// goes forward).
+ /// Pure virtual; defined in AtomicBlackBox and ComplexBlackBox
///
- /// \returns The final status of the box (UPTODATE or MODIFIED)
/// \param caller : The connection which invoked the method; null if called by bbExecute
- ///
- /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always)
- /// then :
- /// - updates its inputs by calling bbUpdateInputs (which recursively calls bbBackwardUpdate on amont boxes)
- /// - calls bbCreateWidget
- /// - calls bbProcess which is the user callback which does the actual processing
- /// - calls bbUpdateChildren
- /// - calls bbShowWidget which shows the widget associated to the box (if any)
- public:
- virtual IOStatus bbBackwardUpdate(Connection* caller) = 0;
- //==================================================================
-
- //==================================================================
- /// Recursive pipeline processing in forward direction along "Child"-"Parent" connections
- /// Pure virtual; defined in UserBlackBox and ComplexBlackBox
- ///
- /// \param caller : The connection which invoked the method
- ///
- /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always)
- /// then :
- /// - calls bbCreateWidget
- /// - calls bbProcess which is the user callback which does the actual processing
- /// - calls bbUpdateChildren which recursively calls bbForwardUpdate on connections attached the "Child" output
- // virtual void bbForwardUpdate(Connection* caller) = 0;
+ virtual void bbBackwardUpdate(Connection::Pointer caller) = 0;
//==================================================================
- protected:
+
//==================================================================
- /// Updates the BlackBox inputs and returns the final status of the inputs
- /// (==UPTODATE iff all inputs are UPTODATE)
- // If excludeParent == true then excludes the amont box connected to input 'Parent' from recursive update
- IOStatus bbUpdateInputs(bool excludeParent=false);
+ /// Updates the BlackBox inputs
+ /// Calls BackwardUpdate on all BlackBoxInputConnector
+ /// \returns The maximum of final IOStatus after each input update
+ IOStatus bbUpdateInputs();
//==================================================================
//==================================================================
- /// Updates the pipeline in amont-aval direction along the "Child"-"Parent" connections only.
- /// Does nothing here. Overloaded in WxContainerBlackbox
- //virtual void bbUpdateChildren( Connection* caller ) { }
+ /// Computes the final IOStatus of inputs and outputs after processing
+ void bbComputePostProcessStatus();
//==================================================================
+
//==================================================================
/// Specific methods for window creation during pipeline execution
/// Creates the window associated to the box (called after bbUpdateInputs)
/// Shows the window associated to the box
/// (called after bbProcess during bbExecute)
/// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox
- virtual void bbShowWindow(Connection* caller) { }
-
+ virtual void bbShowWindow(Connection::Pointer caller) { }
+
virtual void bbHideWindow() {}
+ virtual void bbCloseWindow() { }
//==================================================================
//@}
public:
- static bool bbGlobalGetSomeBoxExecuting()
- { return bbmgSomeBoxExecuting; }
- static void bbGlobalSetSomeBoxExecuting(bool b)
- { bbmgSomeBoxExecuting = b; }
+ static bool bbGlobalGetSomeBoxExecuting();
+ static void bbGlobalSetSomeBoxExecuting(bool b);
-
- static void bbGlobalSetFreezeExecution(bool b) { bbmgFreezeExecution = b;}
- static bool bbGlobalGetFreezeExecution() { return bbmgFreezeExecution; }
+ static void bbGlobalSetFreezeExecution(bool b);
+ static bool bbGlobalGetFreezeExecution();
/// Returns true if the box can "react",
/// which means execute in response to an input change
virtual bool bbCanReact() const;
-
- static void bbGlobalAddToExecutionList( BlackBox* b )
- {
- bbmgExecutionList.insert(b);
-}
+ /// Returns true iff the box is executing
+ bool bbGetExecuting() const { return bbmExecuting; }
+ protected:
+ static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
static void bbGlobalProcessExecutionList();
+ /// Sets the bbmExecuting bool returned by bbGetExecuting
+ void bbSetExecuting(bool b) { bbmExecuting = b; }
//==================================================================
protected:
virtual void bbCopyIOValues(BlackBox& from);
//==================================================================
+ //==================================================================
+ // Black box objects have a special deleter
+ // which must take care of releasing the descriptor
+ // **AFTER** the box is deleted
+ // (Releasing it in the destructor may cause dl close and crash)
+ /// Black box deleter
+ /// 1) Calls the user overloadable bbDelete method
+ /// 2) Releases the box descriptor
+ struct BBTK_EXPORT Deleter : public Object::Deleter
+ {
+ Deleter();
+ void Delete(Object* p);
+ };
+ //==================================================================
+
+ //==================================================================
+ template <class U>
+ static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
+ {
+ return MakePointer(s,BlackBox::Deleter(),lock);
+ }
+ //==================================================================
+
+ //==================================================================
+ virtual void bbDelete() { delete this; }
+ //==================================================================
+
+
+ //==================================================================
private:
-
+ //==================================================================
//==================================================================
- // PRIVATE PART
- /// Default constructor is private : derived classes must use the constructor with the BlackBox's name
- BlackBox() {}
+ // ATTRIBUTES
/// The status of the box
- IOStatus bbmStatus;
+ // IOStatus bbmStatus;
+ /// Is the box executing ?
+ bool bbmExecuting;
/// The name of the black-box
std::string bbmName;
/// The name of the package to which it belongs
std::string bbmPackageName;
-
- /// 0 : "Pipeline" mode : bbUpdate() only calls Process if Status == MODIFIED (normal pipeline processing)
- /// 1 : "Always" mode : bbUpdate() always calls Process
- /// 2 : "Reactive" mode : bbSetModifiedStatus() calls bbUpdate()
+ /// The box processing mode
+ /// 0 : "Pipeline" mode
+ /// 1 : "Always" mode
+ /// 2 : "Reactive" mode
std::string bbmBoxProcessMode;
-
/// The parent of the black box in the ComplexBlackBox hierarchy
- BlackBox::Pointer bbmParent;
+ BlackBox::WeakPointer bbmParent;
//==================================================================
+
//==================================================================
// ATTRIBUTES
/// Map that contains the output connectors of the black box
InputConnectorMapType mInputConnectorMap;
//==================================================================
-
- static bool bbmgSomeBoxExecuting;
- static bool bbmgFreezeExecution;
+ /// The maximum ChangeTime of the inputs
+ // ChangeTime mMaxInputChangeTime;
+ /// The minimum ChangeTime of the outputs
+ // ChangeTime mMinOutputChangeTime;
+
+
+ protected:
+ //=========================================================================
+ /// Sets the ChangeTime of input
+ /*
+ void bbSetInputChangeTime(BlackBoxInputConnector* c,
+ const ChangeTime& t);
+ /// Sets the ChangeTime of output
+ void bbSetOutputChangeTime(BlackBoxOutputConnector* c,
+ const ChangeTime& t);
+ */
+ // void bbUpdateMaxInputChangeTime(const ChangeTime& t);
+ // void bbUpdateMinOutputChangeTime(const ChangeTime& t);
+
+ /// Set the change time of the input
+ // void bbSetInputChangeTime(const std::string& n, ChangeTime);
+ /// Set the change time of the output
+ // void bbSetOutputChangeTime(const std::string& n, ChangeTime);
+
- static std::set<BlackBox*> bbmgExecutionList;
};
// Class BlackBox