]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.h
*** empty log message ***
[bbtk.git] / kernel / src / bbtkBlackBox.h
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkBlackBox.h,v $
4   Language:  C++
5   Date:      $Date: 2008/12/10 09:33:18 $
6   Version:   $Revision: 1.20 $
7 =========================================================================*/
8
9 /* ---------------------------------------------------------------------
10
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
13 *
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.
20 *
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
25 *  liability. 
26 *
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 * ------------------------------------------------------------------------ */                                                                         
30
31
32
33 /**
34  *  \file 
35  *  \brief Class bbtk::BlackBox : abstract black-box interface. 
36  */
37
38 /**
39  * \class bbtk::BlackBox
40  * \brief Abstract black-box interface 
41  */
42  
43 #ifndef __bbtkBlackBox_h__
44 #define __bbtkBlackBox_h__
45
46 #include "bbtkSystem.h"
47 #include "bbtkBlackBoxDescriptor.h"
48 #include "bbtkBlackBoxInputConnector.h"
49 //#include "bbtkBlackBoxOutputConnector.h"
50 #include <set>
51
52 // Signal/slot mechanism for output change events
53 #include <boost/signal.hpp>
54 #include <boost/bind.hpp>
55
56 namespace bbtk
57 {
58
59   
60   struct Void { Void(int = 0) {} };
61   
62   class Factory;
63   class Connection;
64   class BlackBoxOutputConnector;
65  
66
67 #define BBTK_MAKE_OUTPUT_OBSERVER(OBJECT,METHOD) \
68     boost::bind( METHOD, OBJECT, _1, _2, _3)
69
70   class BBTK_EXPORT BlackBox : public Object
71   {
72     BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
73   public: 
74     //==================================================================
75     // INTERFACE
76     //==================================================================
77     typedef boost::signals::trackable OutputChangeObserverType;
78     typedef boost::signal<void (bbtk::BlackBox::Pointer,
79                                 const std::string&,
80                                 IOStatus)>  OutputChangeSignalType;
81     typedef OutputChangeSignalType::slot_function_type 
82     OutputChangeCallbackType;
83  
84     /// The type of map of output connector pointers
85     typedef std::map<std::string, BlackBoxOutputConnector*> 
86     OutputConnectorMapType;
87     /// The type of map of input connector pointers
88     typedef std::map<std::string, BlackBoxInputConnector*> 
89     InputConnectorMapType;
90
91     /// Returns the pointer on the descriptor of the box
92     virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
93
94     /// Returns a pointer on a clone of the box with name <name>
95     virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
96
97     /// User overloadable destruction method of a black box
98     virtual void bbUserDelete();
99
100     /// Returns the Name of the Type of the BlackBox
101     const std::string& bbGetTypeName() const 
102       { return bbGetDescriptor()->GetTypeName(); }
103  
104     
105     /// Returns the name of the BlackBox (instance)
106     const std::string& bbGetName() const { return bbmName; }
107
108     /// Returns the full name of the BlackBox (instance+type)
109     virtual std::string bbGetFullName() const;
110
111     /// Returns the name with the name of the parent prepended if any
112     virtual std::string bbGetNameWithParent() const;
113     
114     /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
115     BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
116
117
118     /// Main processing method of the box.
119     virtual void bbExecute(bool force = false);
120
121
122     /// The type of callback function when an output changes
123     //   typedef BlackBoxOutputConnector::ChangeCallbackType OutputChangeCallbackType;
124
125     /// Adds the function f to the list of functions to call when 
126     /// the output changes.
127     /// f is of type ChangeCallbackType which is basically:
128     /// void (*ChangeCallbackType)(bbtk::BlackBox::Pointer, 
129     ///                            const std::string&,
130     ///                            bbtk::IOStatus)
131     /// To pass a member function 'f' of an instance 'c' of a class 'C' 
132     /// as callback you have to 'bind' it, i.e. call:
133     /// bbAddOutputObserver ( "Out", boost::bind( &C::f , c, _1, _2, _3 ) );
134     /// The convenience macro BBTK_BIND_OUTPUT_OBSERVER ( c, C::f ) does it for you 
135     void bbAddOutputObserver(const std::string& output_name, 
136                              OutputChangeCallbackType f); 
137
138     /// Removes the function f from the list of functions to call when 
139     /// the output changes (TO WRITE)
140     void bbRemoveOutputObserver(const std::string& output_name, 
141                                 OutputChangeCallbackType f); 
142     
143
144     /// Signals that the BlackBox outputs have been modified 
145     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
146     /// This method should be used by widgets in response 
147     /// to user interaction when **ALL** outputs have been modified
148     /// (after the outputs has been updated !).
149     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
150     /// ** USER INTENDED **
151     virtual void bbSignalOutputModification(bool reaction = true);
152     /// Signals that the BlackBox output "output_name" has been modified 
153     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !). 
154     /// This method should be used by widgets in response to user interaction 
155     /// only when **ONE** output has been modified
156     /// (after the output has been updated !)
157     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
158     /// ** USER INTENDED **
159     virtual void bbSignalOutputModification( const std::string& output_name,
160                                              bool reaction = true);
161     /// Signals that the BlackBox vector of outputs "output_name" 
162     /// have been modified.
163     /// Should be used when more than ONE output is modified but not ALL 
164     /// (optimization issue).
165     /// (without marking the box as MODIFIED because its output state is ok). 
166     /// This method should be used by widgets in response to user interaction 
167     /// When more than one output has been changed but not all
168     /// (after the outputs have been updated of course!)
169     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
170     /// ** USER INTENDED **
171     virtual void bbSignalOutputModification( const std::vector<std::string>& 
172                                              output_name,
173                                              bool reaction = true);
174
175     /// Gets the status of the box
176     //    virtual const IOStatus& bbGetStatus() const { return bbmStatus; }
177
178
179     /// Returns true iff the BlackBox has an input of name label
180     virtual bool bbHasInput(const std::string& label) const;
181     /// Returns true iff the BlackBox has an output of name label
182     virtual bool bbHasOutput(const std::string& label) const;
183
184     ///  Gets the input type of a given label
185     virtual TypeInfo bbGetInputType( const std::string &label ) const;
186     ///  Gets the output type of a given label
187     virtual TypeInfo bbGetOutputType( const std::string &label ) const;
188
189     ///  Gets the data of the input called <name>
190     virtual Data bbGetInput( const std::string &name )  = 0;
191     ///  Gets the data of the output called <name>
192     virtual Data bbGetOutput( const std::string &name ) = 0;
193
194     /// Sets the data of the input called <name>.
195     /// If update_time is false then does not update ChangeTime of input
196     virtual void bbSetInput( const std::string &name, Data data,
197                              bool update_time = true ) = 0;
198     virtual void bbBruteForceSetInputPointer( const std::string &name, 
199                                               void* data, 
200                                               bool update_time = true) =0;
201     ///  Sets the data of the output called <name>
202     virtual void bbSetOutput( const std::string &name, Data data) = 0;
203
204
205     /// Gets the status of the input called <name>
206     IOStatus bbGetInputStatus( const std::string &name ) const 
207     { return mInputConnectorMap.find(name)->second->GetStatus(); }
208
209     ///  Returns the input connectors map
210     InputConnectorMapType&  bbGetInputConnectorMap() 
211     { return mInputConnectorMap; }
212     ///  Returns the output connectors map
213     OutputConnectorMapType& bbGetOutputConnectorMap() 
214     { return mOutputConnectorMap; }
215     ///  Returns the input connectors map (const)
216     const InputConnectorMapType&  bbGetInputConnectorMap() const 
217     { return mInputConnectorMap; } 
218     ///  Returns the output connectors map (const)
219     const OutputConnectorMapType& bbGetOutputConnectorMap() const 
220     { return mOutputConnectorMap; }      
221
222     ///  Returns the input connector
223     BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) 
224     { return *(mInputConnectorMap.find(n)->second); }
225     ///  Returns the output connector
226     BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) 
227     { return *(mOutputConnectorMap.find(n)->second); }
228     ///  Returns the input connector (const)
229     const BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) const
230     { return *(mInputConnectorMap.find(n)->second); }
231     ///  Returns the output connector (const)
232     const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const 
233     { return *(mOutputConnectorMap.find(n)->second); }
234
235  
236     
237
238     /// Prints the Help on the BlackBox type 
239     virtual void bbGetHelp(bool full=true) const;
240
241
242     // Returns true iff the box is up-to-date 
243     // (ChangeTime of inputs are all lower strictly to ChangeTime of outputs -
244     //  i.e. max(inputs)<=min(outputs) )
245     //   bool bbIsUpToDate() { return mMaxInputChangeTime < mMinOutputChangeTime; }
246     // Returns true iff the box is out-of-date 
247     // (At least one ChangeTime of an input is greater than one ChangeTime 
248     //  of an output - i.e. max(inputs)>min(outputs))
249     // == !IsUpToDate()
250     //    bool bbIsOutOfDate() { return mMaxInputChangeTime >= mMinOutputChangeTime; }
251
252    //==================================================================
253     // Common inputs / outputs to all boxes
254     /// Returns the value of the input "BoxProcessMode"
255     std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
256     /// Sets the value of the input "BoxProcessMode"
257     void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
258     typedef enum
259       {
260         Pipeline,
261         Always,
262         Reactive
263       }
264       BoxProcessModeValue;
265     /// Returns the "decoded" value of the input "BoxProcessMode"
266     BoxProcessModeValue bbGetBoxProcessModeValue() const;
267   
268     virtual bool bbBoxProcessModeIsReactive() const;
269
270     virtual bool bbBoxProcessModeIsAlways() const;
271
272     /// Returns the value of the input "Execute" 
273     Void bbGetInputBoxExecute() { return Void(); }
274     /// Sets the value of the input "Execute"
275     void bbSetInputBoxExecute(Void = 0) {}
276
277     /// Returns the value of the output "Change"
278     Void bbGetOutputBoxChange() { return Void(); }
279     /// Sets the value of the output "Change" : signal a modification
280     void bbSetOutputBoxChange(Void = 0) { } //bbSetModifiedStatus(); }
281
282     //==================================================================    
283
284
285     //==================================================================    
286
287     /// Does nothing here : overloaded in ComplexBlackBox
288     void bbInsertHTMLGraph(  std::ofstream& s, 
289                              int detail, 
290                              int level,
291                              bool instanceOrtype,
292                              const std::string& output_dir,
293                              bool relative_link ) 
294     {}
295
296     /// Write Graphviz-dot description in file. 
297     /// Here dumps a single box description (i/o) but overloaded 
298     /// in ComplexBlackBox to dump the internal pipeline representation 
299     /// recursing into internal boxes descriptions if level>0.
300     /// detail = 1 : draw inputs and outputs (do not draw otherwise)
301     /// instanceOrtype = true : draw inputs and outputs VALUES 
302     ///  (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
303     /// If relative_link is true then creates relative hrefs
304     virtual void bbWriteDotFileBlackBox(FILE *ff,
305                                         BlackBox::Pointer parentblackbox, 
306                                         int detail, int level, 
307                                         bool instanceOrtype,
308                                         bool relative_link );
309     /// Auxiliary method for bbWriteDotFileBlackBox
310     virtual void bbWriteDotInputOutputName(FILE *ff,
311                                            bool inputoutput, 
312                                            int detail, int level);
313     
314      
315     virtual void bbShowRelations(BlackBox::Pointer parentblackbox, 
316                                  int detail, int level
317                                  );
318     
319     std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
320     std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
321     virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname) 
322     { return BlackBox::Pointer();}
323
324     virtual void Check(bool recursive = true);
325
326         virtual void bbUserOnShow() { }
327         void bbUserOnShowWidget(std::string nameInput);
328
329   protected:
330     //==================================================================
331     // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER 
332     // (IN INHERITED CLASSES)
333     /// Constructor that take the BlackBox's name
334     BlackBox(const std::string &name);
335     /// Constructor from an existing box (copy) with a new name 
336     BlackBox(BlackBox& from, const std::string &name);
337     //==================================================================
338
339
340     //==================================================================
341     /// Signals that the input whose connector is c has changed 
342     /// and propagates the info downward
343     /// ** NOT USER INTENDED **
344     virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* c,
345                                          IOStatus s);
346     //==================================================================
347     
348   private:
349     //==================================================================
350     friend class Connection;
351     friend class ComplexBlackBox;
352
353     /// Sets the parent of the BlackBox
354     void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
355     
356
357     /// Connects the input <name> to the connection c
358     virtual void bbConnectInput( const std::string& name, 
359                                  Connection* c);
360     /// Connects the output <name> to the connection c
361     virtual void bbConnectOutput( const std::string& name, 
362                                   Connection* c);
363     /// Disconnects the input <name> from the connection c
364     virtual void bbDisconnectInput( const std::string& name, 
365                                     Connection* c);
366     /// Disconnects the output <name> from the connection c
367     virtual void bbDisconnectOutput( const std::string& name, 
368                                      Connection* c);
369
370     //==================================================================
371   protected: 
372     /// @name Pipeline processing methods
373     ///  Methods which participate to pipeline processing.
374     ///  Some are pure virtual and prepare particular update mechanism which are implemented by descendents 
375     /// The main method is bbBackwardUpdate which is called by bbExecute and implemented in UserBlackBox and ComplexBlackBox.
376     /// 
377     //@{
378
379     
380     //==================================================================   
381     /// Recursive pipeline processing in backward direction 
382     /// (recursion is in backward direction however execution always 
383     /// goes forward).
384     /// Pure virtual; defined in AtomicBlackBox and ComplexBlackBox
385     /// 
386     /// \param caller : The connection which invoked the method; null if called by bbExecute
387     virtual void bbBackwardUpdate(Connection::Pointer caller) = 0;
388     //==================================================================
389     
390     //==================================================================
391     /// Updates the BlackBox inputs
392     /// Calls BackwardUpdate on all BlackBoxInputConnector
393     /// \returns The maximum of final IOStatus after each input update
394     IOStatus bbUpdateInputs();
395     //==================================================================
396
397     //==================================================================
398     /// Computes the final IOStatus of inputs and outputs after processing
399     void bbComputePostProcessStatus();
400     //==================================================================
401
402  
403     //==================================================================
404     /// Specific methods for window creation during pipeline execution
405     /// Creates the window associated to the box (called after bbUpdateInputs)
406     /// Does nothing here. Overloaded in WxBlackBox.
407     // virtual void bbCreateWindow() { }
408     /// Shows the window associated to the box 
409     /// (called after bbProcess during bbExecute)
410     /// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox
411     virtual void bbShowWindow(Connection::Pointer caller) { }
412
413     virtual void bbHideWindow() {}
414     virtual void bbCloseWindow() { }
415    //==================================================================
416
417     //@}
418   public: 
419
420     static bool bbGlobalGetSomeBoxExecuting();
421     static void bbGlobalSetSomeBoxExecuting(bool b);
422
423     static void bbGlobalSetFreezeExecution(bool b);
424     static bool bbGlobalGetFreezeExecution();
425
426     /// Returns true if the box can "react",
427     /// which means execute in response to an input change 
428     virtual bool bbCanReact() const;
429     
430     /// Returns true iff the box is executing
431     bool bbGetExecuting() const { return bbmExecuting; }
432
433   protected:  
434     static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
435     static void bbGlobalProcessExecutionList();
436     /// Sets the bbmExecuting bool returned by bbGetExecuting
437     void bbSetExecuting(bool b) { bbmExecuting = b; }
438
439     //==================================================================
440   protected:
441     //==================================================================
442     /// Allocates the i/o connectors of the black box
443     virtual void bbAllocateConnectors();
444     /// Desallocates the i/o connectors of the black box
445     virtual void bbDesallocateConnectors();
446     /// Copies the values of the inputs/output from the BlackBox from
447     virtual void bbCopyIOValues(BlackBox& from);
448     //==================================================================
449
450     //==================================================================
451     // Black box objects have a special deleter 
452     // which must take care of releasing the descriptor 
453     // **AFTER** the box is deleted 
454     // (Releasing it in the destructor may cause dl close and crash)
455     /// Black box deleter 
456     /// 1) Calls the user overloadable bbDelete method
457     /// 2) Releases the box descriptor
458     struct BBTK_EXPORT Deleter : public Object::Deleter
459     { 
460       Deleter();
461       void Delete(Object* p);
462     };
463     //==================================================================
464
465     //==================================================================
466     template <class U>
467     static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
468     {
469       return MakePointer(s,BlackBox::Deleter(),lock);
470     }
471     //==================================================================
472
473     //==================================================================
474     virtual void bbDelete() { delete this; }
475     //==================================================================
476
477
478     //==================================================================
479   private:
480     //==================================================================
481  
482     //==================================================================
483     // ATTRIBUTES
484     /// The status of the box
485     //    IOStatus bbmStatus;
486     /// Is the box executing ?
487     bool bbmExecuting;
488     /// The name of the black-box
489     std::string bbmName;
490     /// The name of the package to which it belongs
491     std::string bbmPackageName;
492     /// The box processing mode
493     /// 0 : "Pipeline" mode 
494     /// 1 : "Always" mode 
495     /// 2 : "Reactive" mode 
496     std::string bbmBoxProcessMode;
497     /// The parent of the black box in the ComplexBlackBox hierarchy
498     BlackBox::WeakPointer bbmParent;
499     //==================================================================
500
501
502    //==================================================================
503     // ATTRIBUTES
504     ///  Map that contains the output connectors of the black box
505     OutputConnectorMapType mOutputConnectorMap; 
506     ///  Map that contains the input connectors of the black box
507     InputConnectorMapType mInputConnectorMap;
508     //==================================================================
509
510     /// The maximum ChangeTime of the inputs
511     //    ChangeTime mMaxInputChangeTime;
512     /// The minimum ChangeTime of the outputs
513     //    ChangeTime mMinOutputChangeTime;
514
515
516   protected:
517     //=========================================================================
518     ///  Sets the ChangeTime of input 
519     /*
520     void bbSetInputChangeTime(BlackBoxInputConnector* c, 
521                               const ChangeTime& t);
522     ///  Sets the ChangeTime of output 
523     void bbSetOutputChangeTime(BlackBoxOutputConnector* c, 
524                                const ChangeTime& t);
525     */
526     //   void bbUpdateMaxInputChangeTime(const ChangeTime& t);
527     //    void bbUpdateMinOutputChangeTime(const ChangeTime& t);
528
529     ///  Set the change time of the input 
530     //    void bbSetInputChangeTime(const std::string& n, ChangeTime);
531     ///  Set the change time of the output 
532     //    void bbSetOutputChangeTime(const std::string& n, ChangeTime);
533
534
535
536  };
537   // Class BlackBox
538
539
540
541
542
543
544
545  
546 }
547 // namespace bbtk
548 #endif
549