X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=kernel%2Fsrc%2FbbtkBlackBox.h;h=b70ab75f747a07ad0171f1c07025ebaa9ace7853;hb=13aaa782a7f5942f5072728201750c06afbdfb2d;hp=1c809634ca804e83c65fb75ad934a48115a03c2d;hpb=a26195c366a89795288009cf7e20f11afa494970;p=bbtk.git diff --git a/kernel/src/bbtkBlackBox.h b/kernel/src/bbtkBlackBox.h index 1c80963..b70ab75 100644 --- a/kernel/src/bbtkBlackBox.h +++ b/kernel/src/bbtkBlackBox.h @@ -1,21 +1,34 @@ -/*========================================================================= - +/*========================================================================= 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 @@ -30,12 +43,16 @@ #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 +// Signal/slot mechanism for output change events +#include +#include + namespace bbtk { @@ -43,18 +60,23 @@ 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 OutputChangeSignalType; + typedef OutputChangeSignalType::slot_function_type + OutputChangeCallbackType; + /// The type of map of output connector pointers typedef std::map OutputConnectorMapType; @@ -63,13 +85,11 @@ namespace bbtk 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 - 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(); @@ -85,44 +105,68 @@ namespace bbtk 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& output_name, -bool reaction = true); + /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY + /// ** USER INTENDED ** + virtual void bbSignalOutputModification( const std::vector& + 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 @@ -141,24 +185,15 @@ bool reaction = true); virtual Data bbGetOutput( const std::string &name ) = 0; /// Sets the data of the input called . - /// 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 virtual void bbSetOutput( const std::string &name, Data data) = 0; - /// Connects the input to the connection c - virtual void bbConnectInput( const std::string& name, Connection* c); - /// Connects the output to the connection c - virtual void bbConnectOutput( const std::string& name, Connection* c); - - /// Disconnects the input from the connection c - virtual void bbDisconnectInput( const std::string& name, Connection* c); - /// Disconnects the output from the connection c - virtual void bbDisconnectOutput( const std::string& name, Connection* c); /// Returns the input connectors map InputConnectorMapType& bbGetInputConnectorMap() @@ -172,13 +207,38 @@ bool reaction = true); /// 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; } @@ -206,7 +266,7 @@ bool reaction = true); /// 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(); } //================================================================== @@ -231,7 +291,7 @@ bool reaction = true); /// (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 ); @@ -241,13 +301,19 @@ bool reaction = true); 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: //================================================================== @@ -257,71 +323,77 @@ bool reaction = true); 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 to the connection c + virtual void bbConnectInput( const std::string& name, + Connection* c); + /// Connects the output to the connection c + virtual void bbConnectOutput( const std::string& name, + Connection* c); + /// Disconnects the input from the connection c + virtual void bbDisconnectInput( const std::string& name, + Connection* c); + /// Disconnects the output 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) @@ -330,34 +402,33 @@ bool reaction = true); /// 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: @@ -370,29 +441,58 @@ bool reaction = true); 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 + static boost::shared_ptr 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 @@ -401,12 +501,32 @@ bool reaction = true); 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 bbmgExecutionList; }; // Class BlackBox