OpenWalnut  1.3.1
WModule.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WMODULE_H
26 #define WMODULE_H
27 
28 #include <string>
29 #include <typeinfo>
30 #include <vector>
31 
32 #include <boost/enable_shared_from_this.hpp>
33 #include <boost/filesystem.hpp>
34 #include <boost/function.hpp>
35 #include <boost/shared_ptr.hpp>
36 #include <boost/signals2/signal.hpp>
37 #include <boost/thread.hpp>
38 
39 #include "../common/WConditionSet.h"
40 #include "../common/WLogger.h"
41 #include "../common/WProgress.h"
42 #include "../common/WProgressCombiner.h"
43 #include "../common/WProperties.h"
44 #include "../common/WPrototyped.h"
45 #include "../common/WRequirement.h"
46 #include "../common/WThreadedRunner.h"
47 #include "../dataHandler/WDataSet.h"
48 #include "../dataHandler/WDataSetSingle.h"
49 #include "../dataHandler/WValueSet.h"
50 
51 #include "WModuleCombinerTypes.h"
52 #include "WModuleConnectorSignals.h"
53 #include "WModuleSignals.h"
54 #include "WModuleTypes.h"
55 #include "WModuleMetaInformation.h"
56 
57 class WModuleConnector;
58 class WModuleContainer;
59 class WModuleFactory;
60 class WModuleLoader;
63 template < typename T > class WModuleInputData;
64 template < typename T > class WModuleInputForwardData;
65 template < typename T > class WModuleOutputData;
66 
67 /**
68  * Class representing a single module of OpenWalnut.
69  * \ingroup kernel
70  */
71 class WModule: public WThreadedRunner,
72  public WPrototyped,
73  public boost::enable_shared_from_this< WModule >
74 {
75 friend class WModuleConnector; // requires access to notify members
76 template< typename T > friend class WModuleInputData; // requires access for convenience functions to automatically add a created connector
77 template< typename T > friend class WModuleInputForwardData; // requires access for convenience functions to automatically add a created connector
78 template< typename T > friend class WModuleOutputData; // requires access for convenience functions to automatically add a created connector
79 template< typename T > friend class WModuleOutputForwardData; // requires access for convenience functions to automatically add a created connector
80 friend class WModuleFactory; // for proper creation of module instances, the factory needs access to protected functions.
81  // (especially initialize)
82 friend class WModuleContainer; // for proper management of m_container WModuleContainer needs access.
83 friend class WModuleLoader; // needs to set several protected values like local path and library names.
84 
85 public:
86  /**
87  * Constructs a new WModule instance
88  */
89  WModule();
90 
91  /**
92  * Destructor.
93  */
94  virtual ~WModule();
95 
96  /**
97  * The type for the list of input connectors.
98  */
99  typedef std::vector< boost::shared_ptr< WModuleInputConnector > > InputConnectorList;
100 
101  /**
102  * The type for the list of output connectors.
103  */
104  typedef std::vector< boost::shared_ptr< WModuleOutputConnector > > OutputConnectorList;
105 
106  /**
107  * Shared pointer to a WModule.
108  */
109  typedef boost::shared_ptr< WModule > SPtr;
110 
111  /**
112  * Shared pointer to a const WModule.
113  */
114  typedef boost::shared_ptr< const WModule > ConstSPtr;
115 
116  /**
117  * Gives back input connectors.
118  *
119  * \return the input connectors.
120  */
121  const InputConnectorList& getInputConnectors() const;
122 
123  /**
124  * Finds the named connector for the module.
125  *
126  * \param name the name. This can be a canonical name or the connector name.
127  *
128  * \return the connector.
129  * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
130  */
131  boost::shared_ptr< WModuleInputConnector > getInputConnector( std::string name );
132 
133  /**
134  * Finds the named connector for the module. This is similar to getInputConnector but it does not throw an exception if the connector could
135  * not be found.
136  *
137  * \param name the name. This can be a canonical name or the connector name.
138  *
139  * \return the connector or NULL if not found
140  */
141  boost::shared_ptr< WModuleInputConnector > findInputConnector( std::string name );
142 
143  /**
144  * Gives back output connectors.
145  *
146  * \return the output connectors.
147  */
149 
150  /**
151  * Finds the named connector for the module.
152  *
153  * \param name the name. This can be a canonical name or the connector name.
154  *
155  * \return the connector.
156  * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
157  */
158  boost::shared_ptr< WModuleOutputConnector > getOutputConnector( std::string name );
159 
160  /**
161  * Finds the named connector for the module. This is similar to getOutputConnector but it does not throw an exception if the connector could
162  * not be found.
163  *
164  * \param name the name. This can be a canonical name or the connector name.
165  *
166  * \return the connector or NULL if not found.
167  */
168  boost::shared_ptr< WModuleOutputConnector > findOutputConnector( std::string name );
169 
170  /**
171  * Finds the named connector for the module. This searches for inputs and outputs.
172  *
173  * \param name the name. This can be a canonical name or the connector name.
174  *
175  * \return the connector.
176  * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
177  */
178  boost::shared_ptr< WModuleConnector > getConnector( std::string name );
179 
180  /**
181  * Finds the named connector for the module. This searches for inputs and outputs. This is similar to getConnector but it does not throw an
182  * exception if the connector could not be found.
183  *
184  * \param name the name. This can be a canonical name or the connector name.
185  *
186  * \return the connector or NULL if not found.
187  */
188  boost::shared_ptr< WModuleConnector > findConnector( std::string name );
189 
190  /**
191  * Return a pointer to the properties object of the module.
192  *
193  * \return the properties.
194  */
195  boost::shared_ptr< WProperties > getProperties() const;
196 
197  /**
198  * Return a pointer to the information properties object of the module. The module intends these properties to not be modified.
199  *
200  * \return the properties.
201  */
202  boost::shared_ptr< WProperties > getInformationProperties() const;
203 
204  /**
205  * Determines whether the module instance is properly initialized.
206  *
207  * \return true if properly initialized.
208  */
209  const WBoolFlag& isInitialized() const;
210 
211  /**
212  * Checks whether the module instance is ready to be used. This is the case if isInitialized && isAssociated.
213  *
214  * \return isInitialized && isAssociated
215  */
216  const WBoolFlag& isUseable() const;
217 
218  /**
219  * Checks whether this module is associated with an container.
220  *
221  * \return true if associated.
222  */
223  const WBoolFlag& isAssociated() const;
224 
225  /**
226  * Checks whether this module is ready.
227  *
228  * \return true if ready.
229  */
230  const WBoolFlag& isReady() const;
231 
232  /**
233  * This is the logical or of isReady and isCrashed. You should use this condition if you need to wait for a module to get ready. If it
234  * crashed before ready() got called, you most probably would wait endlessly.
235  *
236  * \return isReady || isCrashed.
237  */
238  const WBoolFlag& isReadyOrCrashed() const;
239 
240  /**
241  * Returns a flag denoting whether the thread currently is running or nor. It is also useful to get a callback whenever a module stops.
242  *
243  * \return the flag
244  */
245  const WBoolFlag& isRunning() const;
246 
247  /**
248  * The container this module is associated with.
249  *
250  * \return the container.
251  */
252  boost::shared_ptr< WModuleContainer > getAssociatedContainer() const;
253 
254  /**
255  * Due to the prototype design pattern used to build modules, this method returns a new instance of this module. NOTE: it
256  * should never be initialized or modified in some other way.
257  *
258  * \return the prototype used to create every module in OpenWalnut.
259  */
260  virtual boost::shared_ptr< WModule > factory() const = 0;
261 
262  /**
263  * Connects a specified notify function with a signal this module instance is offering.
264  *
265  * \exception WModuleSignalSubscriptionFailed thrown if the signal can't be connected.
266  *
267  * \param signal the signal to connect to.
268  * \param notifier the notifier function to bind.
269  *
270  * \return connection descriptor.
271  */
272  virtual boost::signals2::connection subscribeSignal( MODULE_SIGNAL signal, t_ModuleGenericSignalHandlerType notifier );
273 
274  /**
275  * Connects a specified notify function with a signal this module instance is offering. Please note that there also is a
276  * WThreadedRunner::subscribeSignal which allows error callbacks. The difference to this one is that the WThreadedRunner's version does not
277  * provide the sender information (shared_ptr).
278  *
279  * \exception WModuleSignalSubscriptionFailed thrown if the signal can't be connected.
280  *
281  * \param signal the signal to connect to.
282  * \param notifier the notifier function to bind.
283  *
284  * \return connection descriptor.
285  */
286  virtual boost::signals2::connection subscribeSignal( MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier );
287 
288  /**
289  * Gets the modules base progress. This is actually a progress combiner, which bundles all progresses.
290  *
291  * \return the progress combiner for this module.
292  */
293  virtual boost::shared_ptr< WProgressCombiner > getRootProgressCombiner();
294 
295  /**
296  * Get the icon for this module in XPM format.
297  * \return The icon.
298  */
299  virtual const char** getXPMIcon() const;
300 
301  /**
302  * Gets the type of the module. This is useful for FAST differentiation between several modules like standard modules and data
303  * modules which play a special role in OpenWalnut/Kernel.
304  *
305  * \return the Type. If you do not overwrite this method, it will return MODULE_ARBITRARY.
306  */
307  virtual MODULE_TYPE getType() const;
308 
309  /**
310  * Completely disconnects all connected connectors of this module. This is useful to isolate a module (for deletion, removal from a container
311  * and so on.)
312  */
313  void disconnect();
314 
315  /**
316  * Gives a list of all WDisconnectCombiners possible. Please note that while the list exists, connections might change.
317  *
318  * \return the list of possible disconnect operations
319  */
320  WCombinerTypes::WDisconnectList getPossibleDisconnections();
321 
322  /**
323  * Returns the local path of the module. Whenever you try to load local resources, use this path. It is especially useful for shader loading.
324  *
325  * \return the local module path.
326  */
327  boost::filesystem::path getLocalPath() const;
328 
329  /**
330  * Returns the absolute path to the library containing this module.
331  *
332  * \return the path.
333  */
334  boost::filesystem::path getLibPath() const;
335 
336  /**
337  * Returns the name of the package the module belongs to, The package name basically is the name of the
338  * library containing this and maybe other modules. Your build system manages this. The package name is used to identify the resources for
339  * the modules in the library (a.k.a package).
340  *
341  * \return the name
342  */
343  std::string getPackageName() const;
344 
345  /**
346  * Checks whether the module was marked as deprecated.
347  *
348  * \return true if deprecated
349  */
350  bool isDeprecated() const;
351 
352  /**
353  * Queries the deprecation message of a module if specified. If not specified, an empty string is returned. Check \ref isDeprecated first.
354  *
355  * \return deprecation message
356  */
357  std::string getDeprecationMessage() const;
358 
359  /**
360  * The meta information of this module. This contains several information like name, description, icons, help links and so on. It, at least,
361  * contains the name.
362  *
363  * \return the meta info object for this module.
364  */
366 
367 protected:
368  /**
369  * Entry point after loading the module. Runs in separate thread.
370  */
371  virtual void moduleMain() = 0;
372 
373  /**
374  * Thread entry point. Calls moduleMain and sends error notification if needed.
375  */
376  void threadMain();
377 
378  /**
379  * This method is called if an exception was caught, which came from the custom thread code. This method is virtual and allows you to
380  * overwrite the default behaviour. If you overwrite this method, you should call \ref WThreadedRunner::handleDeadlyException or
381  * WThreadedRunner::onThreadException if you are finished with your customized code.
382  *
383  * \param e the exception that was caught.
384  */
385  virtual void onThreadException( const WException& e );
386 
387  /**
388  * Sets the container this module is associated with.
389  *
390  * \param container the container to associate with.
391  */
392  void setAssociatedContainer( boost::shared_ptr< WModuleContainer > container );
393 
394  // **************************************************************************************************************************
395  //
396  // Connector Management
397  //
398  // **************************************************************************************************************************
399 
400  /**
401  * Initialize connectors in this function. This function must not be called multiple times for one module instance.
402  * The module container manages calling those functions -> so just implement it.
403  */
404  virtual void connectors();
405 
406  /**
407  * Initialize properties in this function. This function must not be called multiple times for one module instance.
408  * The module container manages calling those functions -> so just implement it. Once initialized the number and type
409  * of all properties should be set.
410  */
411  virtual void properties();
412 
413  /**
414  * Initialize requirements in this function. This function must not be called multiple times for one module instance.
415  * The module should always implement this. Using this method, a module can tell the kernel what it needs to run properly. For example, it
416  * can require a running graphics engine or, in the case of module containers, other modules.
417  */
418  virtual void requirements();
419 
420  /**
421  * This function allows module programmers to mark their modules deprecated in a user-friendly way. If you implement this function, you need
422  * to specify an text which should mention an alternative module.
423  *
424  * \note do not add sentences like "this module is deprecated" or similar, since the GUI the user is using already shows this message. The
425  * message should say WHY it is deprecated and what alternative module is available.
426  * \return deprecation message
427  */
428  virtual std::string deprecated() const;
429 
430  /**
431  * Manages connector initialization. Gets called by module container.
432  *
433  * \throw WModuleConnectorInitFailed if called multiple times.
434  */
435  void initialize();
436 
437  /**
438  * Called whenever the module should shutdown.
439  */
440  virtual void cleanup();
441 
442  /**
443  * Adds the specified connector to the list of inputs.
444  *
445  * \param con the connector.
446  */
447  void addConnector( boost::shared_ptr<WModuleInputConnector> con );
448 
449  /**
450  * Adds the specified connector to the list of outputs.
451  *
452  * \param con the connector.
453  */
454  void addConnector( boost::shared_ptr<WModuleOutputConnector> con );
455 
456  /**
457  * Removes all connectors properly. It disconnects the connectors and cleans the connectors list.
458  */
459  void removeConnectors();
460 
461  /**
462  * Callback for m_active. Overwrite this in your modules to handle m_active changes separately.
463  */
464  virtual void activate();
465 
466  // **************************************************************************************************************************
467  //
468  // Signal handlers that HAVE to be in every module. By default they do nothing. You should overwrite them to get notified
469  // with the corresponding signal
470  //
471  // **************************************************************************************************************************
472 
473  /**
474  * Gives the signal handler function responsible for a given signal. Modules defining own signal handlers should overwrite
475  * this function. This function is protected since boost::functions are callable, which is what is not wanted here. Just
476  * signals should call them.
477  *
478  * \param signal the signal to get the handler for.
479  *
480  * \return the signal handler for "signal".
481  */
482  virtual const t_GenericSignalHandlerType getSignalHandler( MODULE_CONNECTOR_SIGNAL signal );
483 
484  /**
485  * Gets called whenever a connector gets connected to the specified input.
486  *
487  * \param here the connector of THIS module that got connected to "there"
488  * \param there the connector that has been connected with the connector "here" of this module.
489  */
490  virtual void notifyConnectionEstablished( boost::shared_ptr<WModuleConnector> here,
491  boost::shared_ptr<WModuleConnector> there );
492  /**
493  * Gets called whenever a connection between a remote and local connector gets closed.
494  *
495  * \param here the connector of THIS module getting disconnected.
496  * \param there the connector of the other module getting disconnected.
497  */
498  virtual void notifyConnectionClosed( boost::shared_ptr<WModuleConnector> here, boost::shared_ptr<WModuleConnector> there );
499 
500  /**
501  * Gets called when the data on one input connector changed.
502  *
503  * \param input the input connector receiving the change.
504  * \param output the output connector sending the change notification.
505  */
506  virtual void notifyDataChange( boost::shared_ptr<WModuleConnector> input,
507  boost::shared_ptr<WModuleConnector> output );
508 
509  /**
510  * Call this whenever your module is ready and can react on property changes.
511  */
512  void ready();
513 
514  /**
515  * Logger instance for comfortable info logging. Simply use logInfo() << "my info".
516  *
517  * \return the logger stream.
518  */
520 
521  /**
522  * Logger instance for comfortable debug logging. Simply use logDebug() << "my debug".
523  *
524  * \return the logger stream.
525  */
527 
528  /**
529  * Logger instance for comfortable warning- logs. Simply use logWarning() << "my warning".
530  *
531  * \return the logger stream.
532  */
534 
535  /**
536  * Logger instance for comfortable error logging. Simply use logError() << "my error".
537  *
538  * \return the logger stream.
539  */
541 
542  // **************************************************************************************************************************
543  //
544  // Loading Management
545  //
546  // **************************************************************************************************************************
547 
548  /**
549  * Sets the local module path. This gets called by the module loader.
550  *
551  * \param path the local path.
552  */
553  void setLocalPath( boost::filesystem::path path );
554 
555  /**
556  * Set the path to the library which contains this module. This is usually set by \ref WModuleLoader.
557  *
558  * \param path the path to the library. Needs to be absolute.
559  */
560  void setLibPath( boost::filesystem::path path );
561 
562  /**
563  * Set the package name. This basically is the library name of the lib containing this module. The package name is used to identify resources
564  * and other things which belong to a library (a.k.a. package).
565  *
566  * \param name the name to set
567  */
568  void setPackageName( std::string name );
569 
570  // **************************************************************************************************************************
571  //
572  // Members
573  //
574  // **************************************************************************************************************************
575 
576  /**
577  * The property object for the module.
578  */
579  boost::shared_ptr< WProperties > m_properties;
580 
581  /**
582  * The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION". It is useful to define some property
583  * to only be of informational nature. The GUI does not modify them. As it is a WProperties instance, you can use it the same way as
584  * m_properties.
585  */
586  boost::shared_ptr< WProperties > m_infoProperties;
587 
588  /**
589  * Progress indicator used as parent for all progress' of this module.
590  */
591  boost::shared_ptr< WProgressCombiner > m_progress;
592 
593  /**
594  * True if everything is initialized and ready to be used.
595  */
597 
598  /**
599  * True if container got associated with this flag.
600  */
602 
603  /**
604  * True if associated && initialized.
605  */
607 
608  /**
609  * True if ready() was called.
610  */
612 
613  /**
614  * It is true whenever m_isReady or WThreadedRunner::m_isCrashed is true. This is mostly useful for functions
615  * which need to wait for a module to get ready.
616  */
618 
619  /**
620  * True if the module currently is running.
621  */
623 
624  /**
625  * Progress indicator for the "ready" state.
626  */
627  boost::shared_ptr< WProgress > m_readyProgress;
628 
629  /**
630  * The internal state of the module. This is, by default, simply the exit flag from WThreadedRunner.
631  */
633 
634  /**
635  * The container this module belongs to.
636  */
637  boost::shared_ptr< WModuleContainer > m_container;
638 
639  /**
640  * Set of input connectors associated with this module.
641  */
643 
644  /**
645  * Set of output connectors associated with this module.
646  */
648 
649  /**
650  * True whenever the module should be active
651  */
652  WPropBool m_active;
653 
654  /**
655  * This property holds a user specified name for the current module instance.
656  */
657  WPropString m_runtimeName;
658 
659  /**
660  * The path where the module binary resides in. This path should be used whenever the module needs to load resources. It gets set by the
661  * module loader. Use this to load shaders and so on.
662  */
663  boost::filesystem::path m_localPath;
664 
665  /**
666  * The absolute path to the library containing this module.
667  */
668  boost::filesystem::path m_libPath;
669 
670  /**
671  * The name of the lib/the package containing this module.
672  */
673  std::string m_packageName;
674 
675  /**
676  * The type of the requirement list.
677  */
678  typedef std::vector< WRequirement* > Requirements;
679 
680  /**
681  * The list of requirements.
682  */
684 
685 private:
686  /**
687  * Lock for m_inputConnectors.
688  */
689  // boost::shared_mutex m_inputConnectorsLock;
690 
691  /**
692  * Lock for m_outputConnectors.
693  */
694  // boost::shared_mutex m_outputConnectorsLock;
695 
696  /**
697  * Module meta information. Set by the factory creating the module instance.
698  */
700 
701  /**
702  * Signal fired whenever a module main thread is ready.
703  */
704  t_ModuleGenericSignalType signal_ready;
705 
706  /**
707  * Signal fired whenever a module main thread throws an exception/error.
708  */
709  t_ModuleErrorSignalType signal_error;
710 
711  /**
712  * This method checks whether all the requirements of the module are complied.
713  *
714  * \return the requirement that has failed.
715  */
716  const WRequirement* checkRequirements() const;
717 };
718 
719 /**
720  * Simply a list of modules. The type is used by the following macros and typedefs
721  */
722 typedef std::vector< boost::shared_ptr< WModule > > WModuleList;
723 
724 /**
725  * The signature used for the module loading entry point
726  */
727 typedef void ( *W_LOADABLE_MODULE_SIGNATURE )( WModuleList& );
728 
729 /**
730  * The following macro is used by modules so the factory can acquire a prototype instance from a shared library using the symbol.
731  * You can write this symbol for your own if you need to add multiple modules to the list. This one is for convenience.
732  *
733  * \note we need the module instance to be created using a shared_ptr as WModule is derived from enable_shared_from_this. Removing the shared
734  * pointer causes segmentation faults during load.
735  */
736 #define W_LOADABLE_MODULE( MODULECLASS ) \
737 extern "C" void WLoadModule( WModuleList& m ) { m.push_back( boost::shared_ptr< WModule >( new MODULECLASS ) ); } // NOLINT
738 
739 /**
740  * The corresponding symbol name.
741  */
742 #define W_LOADABLE_MODULE_SYMBOL "WLoadModule"
743 
744 /**
745  * \defgroup modules Modules
746  *
747  * \brief
748  * This group contains modules of OpenWalnut.
749  * The term modules can be understood as "plugin" or "algorithm" in this context.
750  */
751 #endif // WMODULE_H
752