1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.h,v $
5 Date: $Date: 2008/12/08 12:53:47 $
6 Version: $Revision: 1.17 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
14 * This software is governed by the CeCILL-B license under French law and
15 * abiding by the rules of distribution of free software. You can use,
16 * modify and/ or redistribute the software under the terms of the CeCILL-B
17 * license as circulated by CEA, CNRS and INRIA at the following URL
18 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
19 * or in the file LICENSE.txt.
21 * As a counterpart to the access to the source code and rights to copy,
22 * modify and redistribute granted by the license, users are provided only
23 * with a limited warranty and the software's author, the holder of the
24 * economic rights, and the successive licensors have only limited
27 * The fact that you are presently reading this means that you have had
28 * knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */
35 * \brief Class bbtk::BlackBox : abstract black-box interface.
39 * \class bbtk::BlackBox
40 * \brief Abstract black-box interface
43 #ifndef __bbtkBlackBox_h__
44 #define __bbtkBlackBox_h__
46 #include "bbtkSystem.h"
47 #include "bbtkBlackBoxDescriptor.h"
48 #include "bbtkBlackBoxInputConnector.h"
49 //#include "bbtkBlackBoxOutputConnector.h"
52 // Signal/slot mechanism for output change events
53 #include <boost/signal.hpp>
54 #include <boost/bind.hpp>
60 struct Void { Void(int = 0) {} };
64 class BlackBoxOutputConnector;
66 class BBTK_EXPORT BlackBox : public Object
68 BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
70 //==================================================================
72 //==================================================================
73 typedef boost::signals::trackable OutputChangeObserverType;
74 typedef boost::signal<void (bbtk::BlackBox::Pointer,
76 IOStatus)> OutputChangeSignalType;
77 typedef OutputChangeSignalType::slot_function_type
78 OutputChangeCallbackType;
80 /// The type of map of output connector pointers
81 typedef std::map<std::string, BlackBoxOutputConnector*>
82 OutputConnectorMapType;
83 /// The type of map of input connector pointers
84 typedef std::map<std::string, BlackBoxInputConnector*>
85 InputConnectorMapType;
87 /// Returns the pointer on the descriptor of the box
88 virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
90 /// Returns a pointer on a clone of the box with name <name>
91 virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
93 /// User overloadable destruction method of a black box
94 virtual void bbUserDelete();
96 /// Returns the Name of the Type of the BlackBox
97 const std::string& bbGetTypeName() const
98 { return bbGetDescriptor()->GetTypeName(); }
101 /// Returns the name of the BlackBox (instance)
102 const std::string& bbGetName() const { return bbmName; }
104 /// Returns the full name of the BlackBox (instance+type)
105 virtual std::string bbGetFullName() const;
107 /// Returns the name with the name of the parent prepended if any
108 virtual std::string bbGetNameWithParent() const;
110 /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
111 BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
114 /// Main processing method of the box.
115 virtual void bbExecute(bool force = false);
118 /// The type of callback function when an output changes
119 // typedef BlackBoxOutputConnector::ChangeCallbackType OutputChangeCallbackType;
121 /// Adds the function f to the list of functions to call when
122 /// the output changes.
123 /// f is of type ChangeCallbackType which is basically:
124 /// void (*ChangeCallbackType)(BlackBoxOutputConnector*)
125 /// To pass a member function 'f' of an instance 'c' of a class 'C'
126 /// as callback you have to 'bind' it, i.e. call:
127 /// AddChangeObserver ( "Out", boost::bind( &C::f , c, _1 ) );
128 void AddChangeObserver(const std::string& output_name,
129 OutputChangeCallbackType f);
131 /// Removes the function f from the list of functions to call when
132 /// the output changes (TO WRITE)
133 void RemoveChangeObserver(const std::string& output_name,
134 OutputChangeCallbackType f);
137 /// Signals that the BlackBox outputs have been modified
138 /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
139 /// This method should be used by widgets in response
140 /// to user interaction when **ALL** outputs have been modified
141 /// (after the outputs has been updated !).
142 /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
143 /// ** USER INTENDED **
144 virtual void bbSignalOutputModification(bool reaction = true);
145 /// Signals that the BlackBox output "output_name" has been modified
146 /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
147 /// This method should be used by widgets in response to user interaction
148 /// only when **ONE** output has been modified
149 /// (after the output has been updated !)
150 /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
151 /// ** USER INTENDED **
152 virtual void bbSignalOutputModification( const std::string& output_name,
153 bool reaction = true);
154 /// Signals that the BlackBox vector of outputs "output_name"
155 /// have been modified.
156 /// Should be used when more than ONE output is modified but not ALL
157 /// (optimization issue).
158 /// (without marking the box as MODIFIED because its output state is ok).
159 /// This method should be used by widgets in response to user interaction
160 /// When more than one output has been changed but not all
161 /// (after the outputs have been updated of course!)
162 /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
163 /// ** USER INTENDED **
164 virtual void bbSignalOutputModification( const std::vector<std::string>&
166 bool reaction = true);
168 /// Gets the status of the box
169 // virtual const IOStatus& bbGetStatus() const { return bbmStatus; }
172 /// Returns true iff the BlackBox has an input of name label
173 virtual bool bbHasInput(const std::string& label) const;
174 /// Returns true iff the BlackBox has an output of name label
175 virtual bool bbHasOutput(const std::string& label) const;
177 /// Gets the input type of a given label
178 virtual TypeInfo bbGetInputType( const std::string &label ) const;
179 /// Gets the output type of a given label
180 virtual TypeInfo bbGetOutputType( const std::string &label ) const;
182 /// Gets the data of the input called <name>
183 virtual Data bbGetInput( const std::string &name ) = 0;
184 /// Gets the data of the output called <name>
185 virtual Data bbGetOutput( const std::string &name ) = 0;
187 /// Sets the data of the input called <name>.
188 /// If update_time is false then does not update ChangeTime of input
189 virtual void bbSetInput( const std::string &name, Data data,
190 bool update_time = true ) = 0;
191 virtual void bbBruteForceSetInputPointer( const std::string &name,
193 bool update_time = true) =0;
194 /// Sets the data of the output called <name>
195 virtual void bbSetOutput( const std::string &name, Data data) = 0;
198 /// Returns the input connectors map
199 InputConnectorMapType& bbGetInputConnectorMap()
200 { return mInputConnectorMap; }
201 /// Returns the output connectors map
202 OutputConnectorMapType& bbGetOutputConnectorMap()
203 { return mOutputConnectorMap; }
204 /// Returns the input connectors map (const)
205 const InputConnectorMapType& bbGetInputConnectorMap() const
206 { return mInputConnectorMap; }
207 /// Returns the output connectors map (const)
208 const OutputConnectorMapType& bbGetOutputConnectorMap() const
209 { return mOutputConnectorMap; }
211 /// Returns the input connector
212 BlackBoxInputConnector& bbGetInputConnector(const std::string& n)
213 { return *(mInputConnectorMap.find(n)->second); }
214 /// Returns the output connector
215 BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n)
216 { return *(mOutputConnectorMap.find(n)->second); }
217 /// Returns the input connector (const)
218 const BlackBoxInputConnector& bbGetInputConnector(const std::string& n) const
219 { return *(mInputConnectorMap.find(n)->second); }
220 /// Returns the output connector (const)
221 const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const
222 { return *(mOutputConnectorMap.find(n)->second); }
227 /// Prints the Help on the BlackBox type
228 virtual void bbGetHelp(bool full=true) const;
231 // Returns true iff the box is up-to-date
232 // (ChangeTime of inputs are all lower strictly to ChangeTime of outputs -
233 // i.e. max(inputs)<=min(outputs) )
234 // bool bbIsUpToDate() { return mMaxInputChangeTime < mMinOutputChangeTime; }
235 // Returns true iff the box is out-of-date
236 // (At least one ChangeTime of an input is greater than one ChangeTime
237 // of an output - i.e. max(inputs)>min(outputs))
239 // bool bbIsOutOfDate() { return mMaxInputChangeTime >= mMinOutputChangeTime; }
241 //==================================================================
242 // Common inputs / outputs to all boxes
243 /// Returns the value of the input "BoxProcessMode"
244 std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
245 /// Sets the value of the input "BoxProcessMode"
246 void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
254 /// Returns the "decoded" value of the input "BoxProcessMode"
255 BoxProcessModeValue bbGetBoxProcessModeValue() const;
257 virtual bool bbBoxProcessModeIsReactive() const;
259 virtual bool bbBoxProcessModeIsAlways() const;
261 /// Returns the value of the input "Execute"
262 Void bbGetInputBoxExecute() { return Void(); }
263 /// Sets the value of the input "Execute"
264 void bbSetInputBoxExecute(Void = 0) {}
266 /// Returns the value of the output "Change"
267 Void bbGetOutputBoxChange() { return Void(); }
268 /// Sets the value of the output "Change" : signal a modification
269 void bbSetOutputBoxChange(Void = 0) { } //bbSetModifiedStatus(); }
271 //==================================================================
274 //==================================================================
276 /// Does nothing here : overloaded in ComplexBlackBox
277 void bbInsertHTMLGraph( std::ofstream& s,
281 const std::string& output_dir,
285 /// Write Graphviz-dot description in file.
286 /// Here dumps a single box description (i/o) but overloaded
287 /// in ComplexBlackBox to dump the internal pipeline representation
288 /// recursing into internal boxes descriptions if level>0.
289 /// detail = 1 : draw inputs and outputs (do not draw otherwise)
290 /// instanceOrtype = true : draw inputs and outputs VALUES
291 /// (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
292 /// If relative_link is true then creates relative hrefs
293 virtual void bbWriteDotFileBlackBox(FILE *ff,
294 BlackBox::Pointer parentblackbox,
295 int detail, int level,
297 bool relative_link );
298 /// Auxiliary method for bbWriteDotFileBlackBox
299 virtual void bbWriteDotInputOutputName(FILE *ff,
301 int detail, int level);
304 virtual void bbShowRelations(BlackBox::Pointer parentblackbox,
305 int detail, int level
308 std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
309 std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
310 virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname)
311 { return BlackBox::Pointer();}
313 virtual void Check(bool recursive = true);
315 virtual void bbUserOnShow() { }
316 void bbUserOnShowWidget(std::string nameInput);
319 //==================================================================
320 // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER
321 // (IN INHERITED CLASSES)
322 /// Constructor that take the BlackBox's name
323 BlackBox(const std::string &name);
324 /// Constructor from an existing box (copy) with a new name
325 BlackBox(BlackBox& from, const std::string &name);
326 //==================================================================
329 //==================================================================
330 /// Signals that the input whose connector is c has changed
331 /// and propagates the info downward
332 /// ** NOT USER INTENDED **
333 virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* c,
335 /// Signals that the output whose connector is c has changed
336 /// and propagates the info downward
337 /// ** NOT USER INTENDED **
338 virtual void bbSetStatusAndPropagate(BlackBoxOutputConnector* c,
340 //==================================================================
343 //==================================================================
344 friend class Connection;
345 friend class ComplexBlackBox;
347 /// Sets the parent of the BlackBox
348 void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
351 /// Connects the input <name> to the connection c
352 virtual void bbConnectInput( const std::string& name,
354 /// Connects the output <name> to the connection c
355 virtual void bbConnectOutput( const std::string& name,
357 /// Disconnects the input <name> from the connection c
358 virtual void bbDisconnectInput( const std::string& name,
360 /// Disconnects the output <name> from the connection c
361 virtual void bbDisconnectOutput( const std::string& name,
364 //==================================================================
366 /// @name Pipeline processing methods
367 /// Methods which participate to pipeline processing.
368 /// Some are pure virtual and prepare particular update mechanism which are implemented by descendents
369 /// The main method is bbBackwardUpdate which is called by bbExecute and implemented in UserBlackBox and ComplexBlackBox.
374 //==================================================================
375 /// Recursive pipeline processing in backward direction
376 /// (recursion is in backward direction however execution always
378 /// Pure virtual; defined in AtomicBlackBox and ComplexBlackBox
380 /// \param caller : The connection which invoked the method; null if called by bbExecute
381 virtual void bbBackwardUpdate(Connection::Pointer caller) = 0;
382 //==================================================================
384 //==================================================================
385 /// Updates the BlackBox inputs
386 /// Calls BackwardUpdate on all BlackBoxInputConnector
387 /// \returns The maximum of final IOStatus after each input update
388 IOStatus bbUpdateInputs();
389 //==================================================================
391 //==================================================================
392 /// Computes the final IOStatus of inputs and outputs after processing
393 void bbComputePostProcessStatus();
394 //==================================================================
397 //==================================================================
398 /// Specific methods for window creation during pipeline execution
399 /// Creates the window associated to the box (called after bbUpdateInputs)
400 /// Does nothing here. Overloaded in WxBlackBox.
401 // virtual void bbCreateWindow() { }
402 /// Shows the window associated to the box
403 /// (called after bbProcess during bbExecute)
404 /// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox
405 virtual void bbShowWindow(Connection::Pointer caller) { }
407 virtual void bbHideWindow() {}
408 virtual void bbCloseWindow() { }
409 //==================================================================
414 static bool bbGlobalGetSomeBoxExecuting();
415 static void bbGlobalSetSomeBoxExecuting(bool b);
417 static void bbGlobalSetFreezeExecution(bool b);
418 static bool bbGlobalGetFreezeExecution();
420 /// Returns true if the box can "react",
421 /// which means execute in response to an input change
422 virtual bool bbCanReact() const;
424 /// Returns true iff the box is executing
425 bool bbGetExecuting() const { return bbmExecuting; }
428 static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
429 static void bbGlobalProcessExecutionList();
430 /// Sets the bbmExecuting bool returned by bbGetExecuting
431 void bbSetExecuting(bool b) { bbmExecuting = b; }
433 //==================================================================
435 //==================================================================
436 /// Allocates the i/o connectors of the black box
437 virtual void bbAllocateConnectors();
438 /// Desallocates the i/o connectors of the black box
439 virtual void bbDesallocateConnectors();
440 /// Copies the values of the inputs/output from the BlackBox from
441 virtual void bbCopyIOValues(BlackBox& from);
442 //==================================================================
444 //==================================================================
445 // Black box objects have a special deleter
446 // which must take care of releasing the descriptor
447 // **AFTER** the box is deleted
448 // (Releasing it in the destructor may cause dl close and crash)
449 /// Black box deleter
450 /// 1) Calls the user overloadable bbDelete method
451 /// 2) Releases the box descriptor
452 struct BBTK_EXPORT Deleter : public Object::Deleter
455 void Delete(Object* p);
457 //==================================================================
459 //==================================================================
461 static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
463 return MakePointer(s,BlackBox::Deleter(),lock);
465 //==================================================================
467 //==================================================================
468 virtual void bbDelete() { delete this; }
469 //==================================================================
472 //==================================================================
474 //==================================================================
476 //==================================================================
478 /// The status of the box
479 // IOStatus bbmStatus;
480 /// Is the box executing ?
482 /// The name of the black-box
484 /// The name of the package to which it belongs
485 std::string bbmPackageName;
486 /// The box processing mode
487 /// 0 : "Pipeline" mode
488 /// 1 : "Always" mode
489 /// 2 : "Reactive" mode
490 std::string bbmBoxProcessMode;
491 /// The parent of the black box in the ComplexBlackBox hierarchy
492 BlackBox::WeakPointer bbmParent;
493 //==================================================================
496 //==================================================================
498 /// Map that contains the output connectors of the black box
499 OutputConnectorMapType mOutputConnectorMap;
500 /// Map that contains the input connectors of the black box
501 InputConnectorMapType mInputConnectorMap;
502 //==================================================================
504 /// The maximum ChangeTime of the inputs
505 // ChangeTime mMaxInputChangeTime;
506 /// The minimum ChangeTime of the outputs
507 // ChangeTime mMinOutputChangeTime;
511 //=========================================================================
512 /// Sets the ChangeTime of input
514 void bbSetInputChangeTime(BlackBoxInputConnector* c,
515 const ChangeTime& t);
516 /// Sets the ChangeTime of output
517 void bbSetOutputChangeTime(BlackBoxOutputConnector* c,
518 const ChangeTime& t);
520 // void bbUpdateMaxInputChangeTime(const ChangeTime& t);
521 // void bbUpdateMinOutputChangeTime(const ChangeTime& t);
523 /// Set the change time of the input
524 // void bbSetInputChangeTime(const std::string& n, ChangeTime);
525 /// Set the change time of the output
526 // void bbSetOutputChangeTime(const std::string& n, ChangeTime);