]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.h
#3203
[bbtk.git] / kernel / src / bbtkBlackBox.h
1 /*
2  # ---------------------------------------------------------------------
3  #
4  # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5  #                        pour la SantÈ)
6  # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7  # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8  # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9  #
10  #  This software is governed by the CeCILL-B license under French law and
11  #  abiding by the rules of distribution of free software. You can  use,
12  #  modify and/ or redistribute the software under the terms of the CeCILL-B
13  #  license as circulated by CEA, CNRS and INRIA at the following URL
14  #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15  #  or in the file LICENSE.txt.
16  #
17  #  As a counterpart to the access to the source code and  rights to copy,
18  #  modify and redistribute granted by the license, users are provided only
19  #  with a limited warranty  and the software's author,  the holder of the
20  #  economic rights,  and the successive licensors  have only  limited
21  #  liability.
22  #
23  #  The fact that you are presently reading this means that you have had
24  #  knowledge of the CeCILL-B license and that you accept its terms.
25  # ------------------------------------------------------------------------ */
26
27
28 /*=========================================================================
29   Program:   bbtk
30   Module:    $RCSfile: bbtkBlackBox.h,v $
31   Language:  C++
32   Date:      $Date: 2012/11/16 08:49:01 $
33   Version:   $Revision: 1.34 $
34 =========================================================================*/
35
36
37
38 /**
39  *  \file
40  *  \brief Class bbtk::BlackBox : abstract black-box interface.
41  */
42
43 /**
44  * \class bbtk::BlackBox
45  * \brief Abstract black-box interface
46  */
47
48 #ifndef __bbtkBlackBox_h__
49 #define __bbtkBlackBox_h__
50
51 #include "bbtkSystem.h"
52 #include "bbtkMessageManager.h"
53 #include "bbtkBlackBoxDescriptor.h"
54 #include "bbtkBlackBoxInputConnector.h"
55 //#include "bbtkBlackBoxOutputConnector.h"
56 #include <set>
57
58 // Signal/slot mechanism for output change events
59 #include <boost/bind.hpp>
60 #include <boost/signals2/signal.hpp>
61
62
63 #define bbtkBlackBoxMessage(key,level,mess) \
64   bbtkMessage(key,level,"["<<bbGetTypeName()<<":"<<bbGetName()<<"] "<<mess)
65 #define bbtkBlackBoxDebugMessage(key,level,mess)        \
66   bbtkDebugMessage(key,level,"["<<bbGetTypeName()<<":"<<bbGetName()<<"] "<<mess)
67
68 namespace bbtk
69 {
70   struct Void { Void(int = 0) {} };
71
72   class Factory;
73   class Connection;
74   class BlackBoxOutputConnector;
75
76   class BBTK_EXPORT BlackBox : public Object
77   {
78     BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
79
80
81   public:
82
83     //==================================================================
84     // Types
85     //==================================================================
86     typedef boost::signals2::trackable OutputChangeObserverType;
87     typedef boost::signals2::signal<void (bbtk::BlackBox::Pointer,
88                                 const std::string&,
89                                 IOStatus)>  OutputChangeSignalType;
90     typedef OutputChangeSignalType::slot_function_type
91     OutputChangeCallbackType;
92
93     /// The type of map of output connector pointers
94     typedef std::map<std::string, BlackBoxOutputConnector*>
95     OutputConnectorMapType;
96     /// The type of map of input connector pointers
97     typedef std::map<std::string, BlackBoxInputConnector*>
98     InputConnectorMapType;
99     //==================================================================
100
101
102     //==================================================================
103     /// @name Pipeline processing methods
104     ///  Methods which participate to pipeline processing.
105     //@{
106     /// Main processing method of the box.
107     virtual void bbExecute(bool force = false);
108     //@}
109     //==================================================================
110
111
112
113
114
115     //==================================================================
116     /// Returns a pointer on a clone of the box with name <name>
117     virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
118     //==================================================================
119
120
121    //==================================================================
122     /// @name General accessors
123     ///  Methods which give access to general informations on the box
124     //@{
125
126     /// Returns the pointer on the descriptor of the box
127     virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
128
129     /// Returns the Name of the Type of the BlackBox
130     const std::string& bbGetTypeName() const
131       { return bbGetDescriptor()->GetTypeName(); }
132
133
134     /// Returns the name of the BlackBox (instance)
135     const std::string& bbGetName() const { return bbmName; }
136
137     /// Returns the full name of the BlackBox (instance+type)
138     virtual std::string bbGetFullName() const;
139
140     /// Returns the name with the name of the parent prepended if any
141     virtual std::string bbGetNameWithParent() const;
142
143     /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
144     BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
145
146     //@}
147     //==================================================================
148
149
150
151     //==================================================================
152     /// @name Inputs/Outputs related methods
153     ///  Methods related to the box inputs and outputs
154     //@{
155
156     /// Returns true iff the BlackBox has an input of name label
157     virtual bool bbHasInput(const std::string& label) const;
158     ///  Gets the input type of a given label
159     virtual TypeInfo bbGetInputType( const std::string &label ) const;
160     /// Gets the status of the input called <name>
161     IOStatus bbGetInputStatus( const std::string &name ) const
162     { return mInputConnectorMap.find(name)->second->GetStatus(); }
163     ///  Gets the data of the input called <name>
164     virtual Data bbGetInput( const std::string &name )  = 0;
165     ///  Gets the data of the input called <name> as a string using an Adaptor if possible (else returns empty string)
166     std::string bbGetInputAsString( const std::string &input);
167
168
169    /// Sets the data of the input called <name>.
170     /// If update_time is false then does not update ChangeTime of input
171     virtual void bbSetInput( const std::string &name, Data data,
172                              bool update_time = true ) = 0;
173     /// [SYSTEM]: Sets the data of the input called <name> which **MUST* be a pointer
174     virtual void bbBruteForceSetInputPointer( const std::string &name,
175                                               void* data,
176                                               bool update_time = true) =0;
177
178
179     /// Returns true iff the BlackBox has an output of name label
180     virtual bool bbHasOutput(const std::string& label) const;
181     ///  Gets the output type of a given label
182     virtual TypeInfo bbGetOutputType( const std::string &label ) const;
183     ///  Gets the data of the output called <name>
184     virtual Data bbGetOutput( const std::string &name ) = 0;
185     ///  Gets the data of the output called <name> as a string using an Adaptor if possible (else returns empty string)
186     std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
187
188     ///  Sets the data of the output called <name>
189     virtual void bbSetOutput( const std::string &name, Data data) = 0;
190
191
192     ///  Returns the input connectors map
193     InputConnectorMapType&  bbGetInputConnectorMap()
194     { return mInputConnectorMap; }
195     ///  Returns the input connectors map (const)
196     const InputConnectorMapType&  bbGetInputConnectorMap() const
197     { return mInputConnectorMap; }
198    ///  Returns the input connector
199     BlackBoxInputConnector&  bbGetInputConnector(const std::string& n)
200     { return *(mInputConnectorMap.find(n)->second); }
201     ///  Returns the input connector (const)
202     const BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) const
203     { return *(mInputConnectorMap.find(n)->second); }
204
205
206     ///  Returns the output connectors map
207     OutputConnectorMapType& bbGetOutputConnectorMap()
208     { return mOutputConnectorMap; }
209     ///  Returns the output connectors map (const)
210     const OutputConnectorMapType& bbGetOutputConnectorMap() const
211     { return mOutputConnectorMap; }
212     ///  Returns the output connector
213     BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n)
214     { return *(mOutputConnectorMap.find(n)->second); }
215      ///  Returns the output connector (const)
216     const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const
217     { return *(mOutputConnectorMap.find(n)->second); }
218
219     //@}
220     //==================================================================
221
222     /// Prints the Help on the BlackBox type
223     virtual void bbGetHelp(bool full=true) const;
224
225
226
227     //==================================================================
228     /// @name Output signals / observers related methods
229     ///  Methods related to signals emitted by outputs and the
230     //@{
231
232     //==================================================================
233     /// Adds the function f to the list of functions to call when
234     /// the output changes.
235     /// f is of type ChangeCallbackType which is basically:
236     /// void (*ChangeCallbackType)(bbtk::BlackBox::Pointer,
237     ///                            const std::string&,
238     ///                            bbtk::IOStatus)
239     /// To pass a member function 'f' of an instance 'c' of a class 'C'
240     /// as callback you have to 'bind' it, i.e. call:
241     /// bbAddOutputObserver ( "Out", boost::bind( &C::f , c, _1, _2, _3 ) );
242     /// The convenience macro BBTK_BIND_OUTPUT_OBSERVER ( c, C::f ) does it for you
243     void bbAddOutputObserver(const std::string& output_name,
244                              OutputChangeCallbackType f);
245
246     /// Removes the function f from the list of functions to call when
247     /// the output changes (TO WRITE)
248     void bbRemoveOutputObserver(const std::string& output_name,
249                                 OutputChangeCallbackType f);
250    //==================================================================
251
252
253     //==================================================================
254     /// Signals that the BlackBox outputs have been modified
255     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
256     /// This method should be used by widgets in response
257     /// to user interaction when **ALL** outputs have been modified
258     /// (after the outputs has been updated !).
259     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
260     /// ** USER INTENDED **
261     virtual void bbSignalOutputModification(bool reaction = true);
262     /// Signals that the BlackBox output "output_name" has been modified
263     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
264     /// This method should be used by widgets in response to user interaction
265     /// only when **ONE** output has been modified
266     /// (after the output has been updated !)
267     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
268     /// ** USER INTENDED **
269     virtual void bbSignalOutputModification( const std::string& output_name,
270                                              bool reaction = true);
271     /// Signals that the BlackBox vector of outputs "output_name"
272     /// have been modified.
273     /// Should be used when more than ONE output is modified but not ALL
274     /// (optimization issue).
275     /// (without marking the box as MODIFIED because its output state is ok).
276     /// This method should be used by widgets in response to user interaction
277     /// When more than one output has been changed but not all
278     /// (after the outputs have been updated of course!)
279     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
280     /// ** USER INTENDED **
281     virtual void bbSignalOutputModification( const std::vector<std::string>&
282                                              output_name,
283                                              bool reaction = true);
284    //==================================================================
285     //@}
286
287
288
289
290
291
292     //==================================================================
293     /// @name Common inputs / outputs to all boxes
294     //@{
295     /// Returns the value of the input 'BoxProcessMode'
296     std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
297     /// Sets the value of the input 'BoxProcessMode'
298     void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
299     /// The possible values of the input 'BoxProcessMode'
300  
301     typedef enum 
302      {
303       bbPipeline,
304       bbAlways,
305       bbReactive,
306           bbManual
307      }
308     BoxProcessModeValue;
309     
310     /// Returns the "decoded" value of the input "BoxProcessMode"
311     BoxProcessModeValue bbGetBoxProcessModeValue() const;
312     /// Returns true iff the input 'BoxProcessMode' is set to 'Reactive' (or a synonym)
313     virtual bool bbBoxProcessModeIsReactive() const;
314     /// Returns true iff the input 'BoxProcessMode' is set to 'Always' (or a synonym)
315     virtual bool bbBoxProcessModeIsAlways() const;
316         /// Returns true iff the input 'BoxProcessMode' is set to 'Manual' (or a synonym)
317         virtual bool bbBoxProcessModeIsManual() const;
318
319     /// Returns the value of the input 'BoxExecute'
320     Void bbGetInputBoxExecute() { return Void(); }
321     /// Sets the value of the input 'BoxExecute'
322           void bbSetInputBoxExecute(Void = 0) {  }
323
324     /// Returns the value of the output 'BoxChange'
325     Void bbGetOutputBoxChange() { return Void(); }
326     /// Sets the value of the output 'BoxChange'
327     void bbSetOutputBoxChange(Void = 0) {  }
328     //@}
329     //==================================================================
330
331     virtual void bbPrintHelp(BlackBox::Pointer parentblackbox,
332                              int detail, int level
333                              );
334
335     /// Does nothing here : overloaded in ComplexBlackBox
336     void bbInsertHTMLGraph(  std::ofstream& s,
337                              int detail,
338                              int level,
339                              bool instanceOrtype,
340                              const std::string& output_dir,
341                              bool relative_link )
342     {}
343
344
345     //==================================================================
346     /// @name Window related methods
347     //@{
348     virtual void bbSetShown(bool) {}
349     virtual bool bbIsShown() { return false; }
350     //@}
351     //==================================================================
352
353     //JCP changed to public 09-06-09
354         //==================================================================
355             /// @name Manage the execution
356             //@{
357             static bool bbGlobalGetSomeBoxExecuting();
358             static void bbGlobalSetSomeBoxExecuting(bool b);
359
360             static void bbGlobalSetFreezeExecution(bool b);
361             static bool bbGlobalGetFreezeExecution();
362
363             static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
364             static void bbGlobalProcessExecutionList();
365
366             //@}
367     //JCP 09-06-09
368
369   protected:
370
371    //==================================================================
372     /// @name User redefinable methods
373     ///  Virtual methods which can be redefined by inherited classes
374     //@{
375
376     //==================================================================
377     /// User can redefine this method to set
378     /// the default values of the box inputs and outputs
379     /// (it is called in the box constructor)
380     virtual void bbUserSetDefaultValues() {}
381
382     /// User can redefine this method to initialize what must be
383     /// initialized for the box to work, for example allocate dynamic data.
384     /// It is called once and only once before any call to bbUserCreateWidget
385     /// or bbUserProcess.
386     /// What has been allocated here must be desalocated in
387     /// bbFinalizeProcessing
388     virtual void bbUserInitializeProcessing() {}
389
390     /// User must redefine this method to uninitialize what has been
391     /// initialized in bbUserInitializeProcessing,
392     /// typically desallocate memory that has been allocated dynamically.
393     /// It is called in the box destructor if and only if (iff)
394     /// bbUserInitializeProcessing has been called previously.
395     virtual void bbUserFinalizeProcessing() {}
396     ///
397     virtual void bbUserOnShow() {}
398
399     //==================================================================
400     // @}
401     //==================================================================
402
403
404     //==================================================================
405
406     /// Write Graphviz-dot description in file.
407     /// Here dumps a single box description (i/o) but overloaded
408     /// in ComplexBlackBox to dump the internal pipeline representation
409     /// recursing into internal boxes descriptions if level>0.
410     /// detail = 1 : draw inputs and outputs (do not draw otherwise)
411     /// instanceOrtype = true : draw inputs and outputs VALUES
412     ///  (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
413     /// If relative_link is true then creates relative hrefs
414     virtual void bbWriteDotFileBlackBox(FILE *ff,
415                                         BlackBox::Pointer parentblackbox,
416                                         int detail, int level,
417                                         bool instanceOrtype,
418                                         bool relative_link );
419     /// Auxiliary method for bbWriteDotFileBlackBox
420     virtual void bbWriteDotInputOutputName(FILE *ff,
421                                            bool inputoutput,
422                                            int detail, int level);
423
424      virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname)
425               { return BlackBox::Pointer();}
426
427     virtual void Check(bool recursive = true);
428
429     //==================================================================
430     // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER
431     // (IN INHERITED CLASSES)
432     /// Constructor that take the BlackBox's name
433     BlackBox(const std::string &name);
434     /// Constructor from an existing box (copy) with a new name
435     BlackBox(BlackBox& from, const std::string &name);
436     //==================================================================
437
438
439
440     //==================================================================
441     /// @name Pipeline processing methods
442     ///  Methods which participate to pipeline processing.
443     //@{
444     //==================================================================
445     /// Recursive execution method
446     ///
447     /// \param caller : The connection which invoked the method; null if called by bbExecute
448     virtual void bbRecursiveExecute(Connection::Pointer caller);
449     //==================================================================
450
451     //==================================================================
452     /// Updates the BlackBox inputs
453     /// Calls RecursiveExecute on all BlackBoxInputConnector
454     /// \returns The maximum of final IOStatus after each input update
455     IOStatus bbUpdateInputs();
456     //==================================================================
457
458
459     //==================================================================
460     /// Actual CreateWindow method (vitual)
461     /// Overloaded in AtomicBlacBox and descendants
462     virtual void bbCreateWindow()
463     {
464       //  bbtkError("BlackBox::bbCreateWidget called : how can this happen ?");
465     }
466     //==================================================================
467
468     //==================================================================
469     /// Actual ShowWindow method (vitual)
470     /// Overloaded in AtomicBlacBox and descendants
471     virtual void bbShowWindow()
472     {
473       //  bbtkError("BlackBox::bbShowWidget called : how can this happen ?");
474     }
475     //==================================================================
476
477
478    //==================================================================
479     /// Actual processing method (vitual)
480     /// Overloaded in AtomicBlacBox and descendants
481     virtual void bbProcess()
482     {
483       bbtkError("BlackBox::bbProcess called : how can this happen ?");
484 //      this->bbUserProcess();
485     }
486     //==================================================================
487
488     //==================================================================
489     /// Computes the final IOStatus of inputs and outputs after processing
490 virtual    void bbComputePostProcessStatus();
491     //@}
492     //==================================================================
493
494
495     //==================================================================
496     /// Signals that the input whose connector is c has changed
497     /// and propagates the info downward
498     /// ** NOT USER INTENDED **
499     virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* c,
500                                          IOStatus s);
501     //==================================================================
502
503
504
505     //==================================================================
506     /// @name Box con(des)struction / initi(fin)alization methods
507     //@{
508
509     //==================================================================
510     /// Allocates the i/o connectors of the black box
511     virtual void bbAllocateConnectors();
512     /// Desallocates the i/o connectors of the black box
513     virtual void bbDesallocateConnectors();
514     /// Copies the values of the inputs/output from the BlackBox from
515     virtual void bbCopyIOValues(BlackBox& from);
516     //==================================================================
517
518     //==================================================================
519     /// Initializes processing IF NEEDED.
520     /// Calls bbRecursiveInitializeProcessing if the box is in
521     /// "uninitialized" state and put it in "initialized" state.
522     /// On construction, boxes are "uninitialized".
523     /// See also bbFinalizeProcessing
524     void bbInitializeProcessing();
525
526     /// Finalizes processing IF NEEDED.
527     /// Calls bbRecursiveFinalizeProcessing if the box is in
528     /// "initialized" state and put it in "uninitialized" state.
529     /// On construction, boxes are "uninitialized".
530     /// See also bbInitializeProcessing
531     void bbFinalizeProcessing();
532
533     /// Abstract prototype of the method which
534     /// Recursively calls itself for the parent black box and then
535     /// calls bbUserInitializeProcessing for its own class.
536     /// It is redefined in each black box descendant.
537     /// Allows to call bbUserInitializeProcessing for all inherited classes
538     /// (like a constructor does)
539     virtual void bbRecursiveInitializeProcessing() {}
540
541
542     /// Abstract prototype of the method which
543     /// calls bbUserFinalizeProcessing for its own class and then
544     /// recursively calls itself for the parent black box.
545     /// It is redefined in each black box descendant.
546     /// Allows to call bbUserFinalizeProcessing for all inherited classes
547     /// (like a destructor does)
548     virtual void bbRecursiveFinalizeProcessing() {}
549     //==================================================================
550
551     //@}
552     //==================================================================
553
554   private:
555     //==================================================================
556     friend class Connection;
557     friend class ComplexBlackBox;
558
559     /// Sets the parent of the BlackBox
560     void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
561
562     //==================================================================
563     /// @name Input/output connection/disconnection
564     /// INTERNAL METHODS used by a Connection to connect/disconnect
565     /// itself to the i/o connectors of the box
566     //@{
567
568     /// Connects the input <name> to the connection c
569     virtual void bbConnectInput( const std::string& name, Connection* c);
570     /// Connects the output <name> to the connection c
571     virtual void bbConnectOutput( const std::string& name, Connection* c);
572     /// Disconnects the input <name> from the connection c
573     virtual void bbDisconnectInput( const std::string& name, Connection* c);
574     /// Disconnects the output <name> from the connection c
575     virtual void bbDisconnectOutput( const std::string& name, Connection* c);
576     //@}
577     //==================================================================
578
579     /// Returns true if the box can "react",
580     /// which means execute in response to an input change
581     virtual bool bbCanReact() const;
582
583     /// Returns true iff the box is executing
584     bool bbGetExecuting() const { return bbmExecuting; }
585     /// Sets the bbmExecuting bool returned by bbGetExecuting
586     void bbSetExecuting(bool b) { bbmExecuting = b; }
587
588     //==================================================================
589   protected:
590
591
592      //==================================================================
593     /// Black box objects have a special deleter
594     /// which must take care of releasing the descriptor
595     /// **AFTER** the box is deleted
596     /// (Releasing it in the destructor may cause dl close and crash)
597     /// Black box deleter
598     /// 1) Calls the user overloadable bbDelete method
599     /// 2) Releases the box descriptor
600     struct BBTK_EXPORT Deleter : public Object::Deleter
601     {
602       Deleter();
603       int Delete(Object* p);
604     };
605     //==================================================================
606
607     //==================================================================
608     /// Like Object::MakePointer but returns a boost::shared_pointer which uses a BlackBox::Deleter to delete the object instead of the default Object::Deleter
609     template <class U>
610     static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
611     {
612       return MakePointer(s,BlackBox::Deleter(),lock);
613     }
614     //==================================================================
615
616     //==================================================================
617     /// Effective deletion method called by the Deleter.
618     /// The default implementation is to issue 'delete this'
619     /// but it can be redefined in inherited classes to handle special deletion mechanisms (e.g. ref counting, private destructors, such as vtk objects deletion with method Delete, etc.).
620     /// \return The number of remaining references on the object after the call (if meaningfull...): used by bbtk to warn a user if another smart pointing system is still holding the object...
621
622 //JCP 21-09-20 09 delete this throws and exception change due to compiler version changing and boost version
623     virtual int bbDelete() { delete this; 
624                              return 0; }
625     //==================================================================
626
627
628     //==================================================================
629   private:
630     //==================================================================
631
632     //==================================================================
633     // ATTRIBUTES
634     /// Is the box initialized ?
635     bool bbmInitialized;
636     /// Is the box executing ?
637     bool bbmExecuting;
638     /// The name of the black-box
639     std::string bbmName;
640     /// The name of the package to which it belongs
641     std::string bbmPackageName;
642     /// The box processing mode
643     /// 0 : "Pipeline" mode
644     /// 1 : "Always" mode
645     /// 2 : "Reactive" mode
646         /// 3 : "Manual" mode
647     std::string bbmBoxProcessMode;
648     /// The parent of the black box in the ComplexBlackBox hierarchy
649     BlackBox::WeakPointer bbmParent;
650     //==================================================================
651
652
653    //==================================================================
654     // ATTRIBUTES
655     ///  Map that contains the output connectors of the black box
656     OutputConnectorMapType mOutputConnectorMap;
657     ///  Map that contains the input connectors of the black box
658     InputConnectorMapType mInputConnectorMap;
659     //==================================================================
660           
661           
662           bool bbLetRecursiveExecuteManualMode;
663  };
664   // Class BlackBox
665
666
667   /// Convenient macro to create output observer callbacks (freehand functions) from object and method pointer (see samples/SampleOutputObserver)
668 #define BBTK_MAKE_OUTPUT_OBSERVER(OBJECT,METHOD) \
669     boost::bind( METHOD, OBJECT, _1, _2, _3)
670
671 }
672 // namespace bbtk
673 #endif