]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.h
Fixed Window deletion mechanism
[bbtk.git] / kernel / src / bbtkBlackBox.h
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkBlackBox.h,v $
4   Language:  C++
5   Date:      $Date: 2009/05/28 08:12:05 $
6   Version:   $Revision: 1.26 $
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 "bbtkMessageManager.h"
48 #include "bbtkBlackBoxDescriptor.h"
49 #include "bbtkBlackBoxInputConnector.h"
50 //#include "bbtkBlackBoxOutputConnector.h"
51 #include <set>
52
53 // Signal/slot mechanism for output change events
54 #include <boost/signal.hpp>
55 #include <boost/bind.hpp>
56
57
58 #define bbtkBlackBoxMessage(key,level,mess) \
59   bbtkMessage(key,level,"["<<bbGetName()<<"] "<<mess)
60 #define bbtkBlackBoxDebugMessage(key,level,mess)        \
61   bbtkDebugMessage(key,level,"["<<bbGetName()<<"] "<<mess)
62
63 namespace bbtk
64 {
65
66   
67   struct Void { Void(int = 0) {} };
68   
69   class Factory;
70   class Connection;
71   class BlackBoxOutputConnector;
72  
73
74
75   class BBTK_EXPORT BlackBox : public Object
76   {
77     BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
78   public: 
79     //==================================================================
80     // INTERFACE
81     //==================================================================
82     typedef boost::signals::trackable OutputChangeObserverType;
83     typedef boost::signal<void (bbtk::BlackBox::Pointer,
84                                 const std::string&,
85                                 IOStatus)>  OutputChangeSignalType;
86     typedef OutputChangeSignalType::slot_function_type 
87     OutputChangeCallbackType;
88  
89     /// The type of map of output connector pointers
90     typedef std::map<std::string, BlackBoxOutputConnector*> 
91     OutputConnectorMapType;
92     /// The type of map of input connector pointers
93     typedef std::map<std::string, BlackBoxInputConnector*> 
94     InputConnectorMapType;
95
96     /// Returns the pointer on the descriptor of the box
97     virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
98
99     /// Returns a pointer on a clone of the box with name <name>
100     virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
101
102     /// User overloadable destruction method of a black box
103     virtual void bbUserDelete();
104
105     /// Returns the Name of the Type of the BlackBox
106     const std::string& bbGetTypeName() const 
107       { return bbGetDescriptor()->GetTypeName(); }
108  
109     
110     /// Returns the name of the BlackBox (instance)
111     const std::string& bbGetName() const { return bbmName; }
112
113     /// Returns the full name of the BlackBox (instance+type)
114     virtual std::string bbGetFullName() const;
115
116     /// Returns the name with the name of the parent prepended if any
117     virtual std::string bbGetNameWithParent() const;
118     
119     /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
120     BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
121
122
123     /// Main processing method of the box.
124     virtual void bbExecute(bool force = false);
125
126
127  
128  
129
130
131     /// Returns true iff the BlackBox has an input of name label
132     virtual bool bbHasInput(const std::string& label) const;
133     /// Returns true iff the BlackBox has an output of name label
134     virtual bool bbHasOutput(const std::string& label) const;
135
136     ///  Gets the input type of a given label
137     virtual TypeInfo bbGetInputType( const std::string &label ) const;
138     ///  Gets the output type of a given label
139     virtual TypeInfo bbGetOutputType( const std::string &label ) const;
140
141     ///  Gets the data of the input called <name>
142     virtual Data bbGetInput( const std::string &name )  = 0;
143     ///  Gets the data of the output called <name>
144     virtual Data bbGetOutput( const std::string &name ) = 0;
145
146     /// Sets the data of the input called <name>.
147     /// If update_time is false then does not update ChangeTime of input
148     virtual void bbSetInput( const std::string &name, Data data,
149                              bool update_time = true ) = 0;
150     virtual void bbBruteForceSetInputPointer( const std::string &name, 
151                                               void* data, 
152                                               bool update_time = true) =0;
153     ///  Sets the data of the output called <name>
154     virtual void bbSetOutput( const std::string &name, Data data) = 0;
155
156
157     /// Gets the status of the input called <name>
158     IOStatus bbGetInputStatus( const std::string &name ) const 
159     { return mInputConnectorMap.find(name)->second->GetStatus(); }
160
161     ///  Returns the input connectors map
162     InputConnectorMapType&  bbGetInputConnectorMap() 
163     { return mInputConnectorMap; }
164     ///  Returns the output connectors map
165     OutputConnectorMapType& bbGetOutputConnectorMap() 
166     { return mOutputConnectorMap; }
167     ///  Returns the input connectors map (const)
168     const InputConnectorMapType&  bbGetInputConnectorMap() const 
169     { return mInputConnectorMap; } 
170     ///  Returns the output connectors map (const)
171     const OutputConnectorMapType& bbGetOutputConnectorMap() const 
172     { return mOutputConnectorMap; }      
173
174     ///  Returns the input connector
175     BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) 
176     { return *(mInputConnectorMap.find(n)->second); }
177     ///  Returns the output connector
178     BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) 
179     { return *(mOutputConnectorMap.find(n)->second); }
180     ///  Returns the input connector (const)
181     const BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) const
182     { return *(mInputConnectorMap.find(n)->second); }
183     ///  Returns the output connector (const)
184     const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const 
185     { return *(mOutputConnectorMap.find(n)->second); }
186
187  
188     
189
190     /// Prints the Help on the BlackBox type 
191     virtual void bbGetHelp(bool full=true) const;
192
193     //==================================================================
194     /// Adds the function f to the list of functions to call when 
195     /// the output changes.
196     /// f is of type ChangeCallbackType which is basically:
197     /// void (*ChangeCallbackType)(bbtk::BlackBox::Pointer, 
198     ///                            const std::string&,
199     ///                            bbtk::IOStatus)
200     /// To pass a member function 'f' of an instance 'c' of a class 'C' 
201     /// as callback you have to 'bind' it, i.e. call:
202     /// bbAddOutputObserver ( "Out", boost::bind( &C::f , c, _1, _2, _3 ) );
203     /// The convenience macro BBTK_BIND_OUTPUT_OBSERVER ( c, C::f ) does it for you 
204     void bbAddOutputObserver(const std::string& output_name, 
205                              OutputChangeCallbackType f); 
206
207     /// Removes the function f from the list of functions to call when 
208     /// the output changes (TO WRITE)
209     void bbRemoveOutputObserver(const std::string& output_name, 
210                                 OutputChangeCallbackType f); 
211    //==================================================================
212     
213
214     //==================================================================
215     /// Signals that the BlackBox outputs have been modified 
216     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
217     /// This method should be used by widgets in response 
218     /// to user interaction when **ALL** outputs have been modified
219     /// (after the outputs has been updated !).
220     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
221     /// ** USER INTENDED **
222     virtual void bbSignalOutputModification(bool reaction = true);
223     /// Signals that the BlackBox output "output_name" has been modified 
224     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !). 
225     /// This method should be used by widgets in response to user interaction 
226     /// only when **ONE** output has been modified
227     /// (after the output has been updated !)
228     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
229     /// ** USER INTENDED **
230     virtual void bbSignalOutputModification( const std::string& output_name,
231                                              bool reaction = true);
232     /// Signals that the BlackBox vector of outputs "output_name" 
233     /// have been modified.
234     /// Should be used when more than ONE output is modified but not ALL 
235     /// (optimization issue).
236     /// (without marking the box as MODIFIED because its output state is ok). 
237     /// This method should be used by widgets in response to user interaction 
238     /// When more than one output has been changed but not all
239     /// (after the outputs have been updated of course!)
240     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
241     /// ** USER INTENDED **
242     virtual void bbSignalOutputModification( const std::vector<std::string>& 
243                                              output_name,
244                                              bool reaction = true);
245    //==================================================================
246
247
248
249     //==================================================================
250    /// User can redefine this method to set 
251     /// the default values of the box inputs and outputs
252     /// (it is called in the box constructor)
253     virtual void bbUserSetDefaultValues() {}
254
255     /// User can redefine this method to initialize what must be 
256     /// initialized for the box to work, for example allocate dynamic data.
257     /// It is called once and only once before any call to bbUserCreateWidget
258     /// or bbUserProcess.
259     /// What has been allocated here must be desalocated in 
260     /// bbFinalizeProcessing
261     virtual void bbUserInitializeProcessing() {}
262
263     /// User must redefine this method to uninitialize what has been
264     /// initialized in bbUserInitializeProcessing,
265     /// typically desallocate memory that has been allocated dynamically.
266     /// It is called in the box destructor if and only if (iff) 
267     /// bbUserInitializeProcessing has been called previously.
268     virtual void bbUserFinalizeProcessing() {}
269
270
271     /// Initializes processing IF NEEDED. 
272     /// Calls bbRecursiveInitializeProcessing if the box is in 
273     /// "uninitialized" state and put it in "initialized" state.
274     /// On construction, boxes are "uninitialized".
275     /// See also bbFinalizeProcessing
276     void bbInitializeProcessing();
277
278     /// Finalizes processing IF NEEDED.
279     /// Calls bbRecursiveFinalizeProcessing if the box is in 
280     /// "initialized" state and put it in "uninitialized" state.
281     /// On construction, boxes are "uninitialized".
282     /// See also bbInitializeProcessing
283     void bbFinalizeProcessing();
284
285     /// Abstract prototype of the method which 
286     /// Recursively calls itself for the parent black box and then
287     /// calls bbUserInitializeProcessing for its own class. 
288     /// It is redefined in each black box descendant.
289     /// Allows to call bbUserInitializeProcessing for all inherited classes
290     /// (like a constructor does)
291     virtual void bbRecursiveInitializeProcessing() {}
292
293
294     /// Abstract prototype of the method which 
295     /// calls bbUserFinalizeProcessing for its own class and then 
296     /// recursively calls itself for the parent black box.
297     /// It is redefined in each black box descendant.
298     /// Allows to call bbUserFinalizeProcessing for all inherited classes
299     /// (like a destructor does)
300    virtual void bbRecursiveFinalizeProcessing() {}
301
302     //==================================================================
303
304
305    //==================================================================
306     // Common inputs / outputs to all boxes
307     /// Returns the value of the input "BoxProcessMode"
308     std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
309     /// Sets the value of the input "BoxProcessMode"
310     void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
311     typedef enum
312       {
313         Pipeline,
314         Always,
315         Reactive
316       }
317       BoxProcessModeValue;
318     /// Returns the "decoded" value of the input "BoxProcessMode"
319     BoxProcessModeValue bbGetBoxProcessModeValue() const;
320   
321     virtual bool bbBoxProcessModeIsReactive() const;
322
323     virtual bool bbBoxProcessModeIsAlways() const;
324
325     /// Returns the value of the input "Execute" 
326     Void bbGetInputBoxExecute() { return Void(); }
327     /// Sets the value of the input "Execute"
328     void bbSetInputBoxExecute(Void = 0) {}
329
330     /// Returns the value of the output "Change"
331     Void bbGetOutputBoxChange() { return Void(); }
332     /// Sets the value of the output "Change" : signal a modification
333     void bbSetOutputBoxChange(Void = 0) { } //bbSetModifiedStatus(); }
334
335     //==================================================================    
336
337
338     //==================================================================    
339
340     /// Does nothing here : overloaded in ComplexBlackBox
341     void bbInsertHTMLGraph(  std::ofstream& s, 
342                              int detail, 
343                              int level,
344                              bool instanceOrtype,
345                              const std::string& output_dir,
346                              bool relative_link ) 
347     {}
348
349     /// Write Graphviz-dot description in file. 
350     /// Here dumps a single box description (i/o) but overloaded 
351     /// in ComplexBlackBox to dump the internal pipeline representation 
352     /// recursing into internal boxes descriptions if level>0.
353     /// detail = 1 : draw inputs and outputs (do not draw otherwise)
354     /// instanceOrtype = true : draw inputs and outputs VALUES 
355     ///  (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
356     /// If relative_link is true then creates relative hrefs
357     virtual void bbWriteDotFileBlackBox(FILE *ff,
358                                         BlackBox::Pointer parentblackbox, 
359                                         int detail, int level, 
360                                         bool instanceOrtype,
361                                         bool relative_link );
362     /// Auxiliary method for bbWriteDotFileBlackBox
363     virtual void bbWriteDotInputOutputName(FILE *ff,
364                                            bool inputoutput, 
365                                            int detail, int level);
366     
367      
368     virtual void bbShowRelations(BlackBox::Pointer parentblackbox, 
369                                  int detail, int level
370                                  );
371     
372     std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
373     std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
374     virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname) 
375     { return BlackBox::Pointer();}
376
377     virtual void Check(bool recursive = true);
378
379     virtual void bbSetShown(bool) {}
380     virtual bool bbIsShown() { return false; }
381     virtual void bbUserOnShow() {}
382
383   protected:
384     //==================================================================
385     // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER 
386     // (IN INHERITED CLASSES)
387     /// Constructor that take the BlackBox's name
388     BlackBox(const std::string &name);
389     /// Constructor from an existing box (copy) with a new name 
390     BlackBox(BlackBox& from, const std::string &name);
391     //==================================================================
392
393
394     //==================================================================
395     /// Signals that the input whose connector is c has changed 
396     /// and propagates the info downward
397     /// ** NOT USER INTENDED **
398     virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* c,
399                                          IOStatus s);
400     //==================================================================
401     
402   private:
403     //==================================================================
404     friend class Connection;
405     friend class ComplexBlackBox;
406
407     /// Sets the parent of the BlackBox
408     void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
409     
410
411     /// Connects the input <name> to the connection c
412     virtual void bbConnectInput( const std::string& name, 
413                                  Connection* c);
414     /// Connects the output <name> to the connection c
415     virtual void bbConnectOutput( const std::string& name, 
416                                   Connection* c);
417     /// Disconnects the input <name> from the connection c
418     virtual void bbDisconnectInput( const std::string& name, 
419                                     Connection* c);
420     /// Disconnects the output <name> from the connection c
421     virtual void bbDisconnectOutput( const std::string& name, 
422                                      Connection* c);
423
424     //==================================================================
425   protected: 
426     /// @name Pipeline processing methods
427     ///  Methods which participate to pipeline processing.
428     //@{
429
430     
431     //==================================================================   
432     /// Recursive execution method
433     /// 
434     /// \param caller : The connection which invoked the method; null if called by bbExecute
435     virtual void bbRecursiveExecute(Connection::Pointer caller);
436     //==================================================================
437     
438     //==================================================================
439     /// Updates the BlackBox inputs
440     /// Calls RecursiveExecute on all BlackBoxInputConnector
441     /// \returns The maximum of final IOStatus after each input update
442     IOStatus bbUpdateInputs();
443     //==================================================================
444
445           
446     //==================================================================
447     /// Actual CreateWindow method (vitual)
448     /// Overloaded in AtomicBlacBox and descendants 
449     virtual void bbCreateWindow()
450     {
451       //  bbtkError("BlackBox::bbCreateWidget called : how can this happen ?");
452     }
453     //==================================================================
454     
455     //==================================================================
456     /// Actual ShowWindow method (vitual)
457     /// Overloaded in AtomicBlacBox and descendants 
458     virtual void bbShowWindow()
459     {
460       //  bbtkError("BlackBox::bbShowWidget called : how can this happen ?");
461     }
462     //==================================================================
463     
464                   
465    //==================================================================
466     /// Actual processing method (vitual)
467     /// Overloaded in AtomicBlacBox and descendants 
468     virtual void bbProcess() 
469     {
470       bbtkError("BlackBox::bbProcess called : how can this happen ?");
471 //      this->bbUserProcess(); 
472     }
473     //==================================================================
474
475     //==================================================================
476     /// Computes the final IOStatus of inputs and outputs after processing
477     void bbComputePostProcessStatus();
478     //==================================================================
479
480     //@}
481   public: 
482
483     static bool bbGlobalGetSomeBoxExecuting();
484     static void bbGlobalSetSomeBoxExecuting(bool b);
485
486     static void bbGlobalSetFreezeExecution(bool b);
487     static bool bbGlobalGetFreezeExecution();
488
489     /// Returns true if the box can "react",
490     /// which means execute in response to an input change 
491     virtual bool bbCanReact() const;
492     
493     /// Returns true iff the box is executing
494     bool bbGetExecuting() const { return bbmExecuting; }
495
496   protected:  
497     static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
498     static void bbGlobalProcessExecutionList();
499     /// Sets the bbmExecuting bool returned by bbGetExecuting
500     void bbSetExecuting(bool b) { bbmExecuting = b; }
501
502     //==================================================================
503   protected:
504     //==================================================================
505     /// Allocates the i/o connectors of the black box
506     virtual void bbAllocateConnectors();
507     /// Desallocates the i/o connectors of the black box
508     virtual void bbDesallocateConnectors();
509     /// Copies the values of the inputs/output from the BlackBox from
510     virtual void bbCopyIOValues(BlackBox& from);
511     //==================================================================
512
513     //==================================================================
514     // Black box objects have a special deleter 
515     // which must take care of releasing the descriptor 
516     // **AFTER** the box is deleted 
517     // (Releasing it in the destructor may cause dl close and crash)
518     /// Black box deleter 
519     /// 1) Calls the user overloadable bbDelete method
520     /// 2) Releases the box descriptor
521     struct BBTK_EXPORT Deleter : public Object::Deleter
522     { 
523       Deleter(); 
524       int Delete(Object* p);
525     };
526     //==================================================================
527
528     //==================================================================
529     template <class U>
530     static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
531     {
532       return MakePointer(s,BlackBox::Deleter(),lock);
533     }
534     //==================================================================
535
536     //==================================================================
537     virtual int bbDelete() { delete this; return 0; }
538     //==================================================================
539
540
541     //==================================================================
542   private:
543     //==================================================================
544  
545     //==================================================================
546     // ATTRIBUTES
547     /// Is the box initialized ?
548     bool bbmInitialized;
549     /// Is the box executing ?
550     bool bbmExecuting;
551     /// The name of the black-box
552     std::string bbmName;
553     /// The name of the package to which it belongs
554     std::string bbmPackageName;
555     /// The box processing mode
556     /// 0 : "Pipeline" mode 
557     /// 1 : "Always" mode 
558     /// 2 : "Reactive" mode 
559     std::string bbmBoxProcessMode;
560     /// The parent of the black box in the ComplexBlackBox hierarchy
561     BlackBox::WeakPointer bbmParent;
562     //==================================================================
563
564
565    //==================================================================
566     // ATTRIBUTES
567     ///  Map that contains the output connectors of the black box
568     OutputConnectorMapType mOutputConnectorMap; 
569     ///  Map that contains the input connectors of the black box
570     InputConnectorMapType mInputConnectorMap;
571     //==================================================================
572
573
574  };
575   // Class BlackBox
576
577
578
579   /// Convenient macro to create output observer callbacks (freehand functions) from object and method pointer (see samples/SampleOutputObserver)
580 #define BBTK_MAKE_OUTPUT_OBSERVER(OBJECT,METHOD) \
581     boost::bind( METHOD, OBJECT, _1, _2, _3)
582
583
584
585
586  
587 }
588 // namespace bbtk
589 #endif
590