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