OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
WModule.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WMODULE_H
00026 #define WMODULE_H
00027 
00028 #include <string>
00029 #include <typeinfo>
00030 #include <vector>
00031 
00032 #include <boost/enable_shared_from_this.hpp>
00033 // Use filesystem version 2 for compatibility with newer boost versions.
00034 #ifndef BOOST_FILESYSTEM_VERSION
00035     #define BOOST_FILESYSTEM_VERSION 2
00036 #endif
00037 #include <boost/filesystem.hpp>
00038 #include <boost/function.hpp>
00039 #include <boost/shared_ptr.hpp>
00040 #include <boost/signals2/signal.hpp>
00041 #include <boost/thread.hpp>
00042 
00043 #include "../common/WConditionSet.h"
00044 #include "../common/WLogger.h"
00045 #include "../common/WProgress.h"
00046 #include "../common/WProgressCombiner.h"
00047 #include "../common/WProperties.h"
00048 #include "../common/WPrototyped.h"
00049 #include "../common/WRequirement.h"
00050 #include "../common/WThreadedRunner.h"
00051 #include "../dataHandler/WDataSet.h"
00052 #include "../dataHandler/WDataSetSingle.h"
00053 #include "../dataHandler/WValueSet.h"
00054 #include "WExportKernel.h"
00055 #include "WModuleCombinerTypes.h"
00056 #include "WModuleConnectorSignals.h"
00057 #include "WModuleSignals.h"
00058 #include "WModuleTypes.h"
00059 
00060 class WModuleConnector;
00061 class WModuleContainer;
00062 class WModuleFactory;
00063 class WModuleInputConnector;
00064 class WModuleOutputConnector;
00065 template < typename T > class WModuleInputData;
00066 template < typename T > class WModuleInputForwardData;
00067 template < typename T > class WModuleOutputData;
00068 
00069 /**
00070  * Class representing a single module of OpenWalnut.
00071  * \ingroup kernel
00072  */
00073 class OWKERNEL_EXPORT WModule: public WThreadedRunner,
00074                                public WPrototyped,
00075                                public boost::enable_shared_from_this< WModule >
00076 {
00077 friend class WModuleConnector;  // requires access to notify members
00078 template< typename T > friend class WModuleInputData;  // requires access for convenience functions to automatically add a created connector
00079 template< typename T > friend class WModuleInputForwardData;  // requires access for convenience functions to automatically add a created connector
00080 template< typename T > friend class WModuleOutputData;  // requires access for convenience functions to automatically add a created connector
00081 friend class WModuleFactory;    // for proper creation of module instances, the factory needs access to protected functions.
00082                                 // (especially initialize)
00083 friend class WModuleContainer;  // for proper management of m_container WModuleContainer needs access.
00084 
00085 public:
00086 
00087     /**
00088      * Constructs a new WModule instance
00089      */
00090     WModule();
00091 
00092     /**
00093      * Destructor.
00094      */
00095     virtual ~WModule();
00096 
00097     /**
00098      * The type for the list of input connectors.
00099      */
00100     typedef std::vector< boost::shared_ptr< WModuleInputConnector > > InputConnectorList;
00101 
00102     /**
00103      * The type for the list of output connectors.
00104      */
00105     typedef std::vector< boost::shared_ptr< WModuleOutputConnector > > OutputConnectorList;
00106 
00107     /**
00108      * Shared pointer to a WModule.
00109      */
00110     typedef boost::shared_ptr< WModule > SPtr;
00111 
00112     /**
00113      * Shared pointer to a const WModule.
00114      */
00115     typedef boost::shared_ptr< const WModule > ConstSPtr;
00116 
00117     /**
00118      * Gives back input connectors.
00119      *
00120      * \return the input connectors.
00121      */
00122     const InputConnectorList& getInputConnectors() const;
00123 
00124     /**
00125      * Finds the named connector for the module.
00126      *
00127      * \param name the name. This can be a canonical name or the connector name.
00128      *
00129      * \return the connector.
00130      * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
00131      */
00132     boost::shared_ptr< WModuleInputConnector > getInputConnector( std::string name );
00133 
00134     /**
00135      * Finds the named connector for the module. This is similar to getInputConnector but it does not throw an exception if the connector could
00136      * not be found.
00137      *
00138      * \param name the name. This can be a canonical name or the connector name.
00139      *
00140      * \return the connector or NULL if not found
00141      */
00142     boost::shared_ptr< WModuleInputConnector > findInputConnector( std::string name );
00143 
00144     /**
00145      * Gives back output connectors.
00146      *
00147      * \return the output connectors.
00148      */
00149     const OutputConnectorList& getOutputConnectors() const;
00150 
00151     /**
00152      * Finds the named connector for the module.
00153      *
00154      * \param name the name. This can be a canonical name or the connector name.
00155      *
00156      * \return the connector.
00157      * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
00158      */
00159     boost::shared_ptr< WModuleOutputConnector > getOutputConnector( std::string name );
00160 
00161     /**
00162      * Finds the named connector for the module. This is similar to getOutputConnector but it does not throw an exception if the connector could
00163      * not be found.
00164      *
00165      * \param name the name. This can be a canonical name or the connector name.
00166      *
00167      * \return the connector or NULL if not found.
00168      */
00169     boost::shared_ptr< WModuleOutputConnector > findOutputConnector( std::string name );
00170 
00171     /**
00172      * Finds the named connector for the module. This searches for inputs and outputs.
00173      *
00174      * \param name the name. This can be a canonical name or the connector name.
00175      *
00176      * \return the connector.
00177      * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
00178      */
00179     boost::shared_ptr< WModuleConnector > getConnector( std::string name );
00180 
00181     /**
00182      * Finds the named connector for the module. This searches for inputs and outputs. This is similar to getConnector but it does not throw an
00183      * exception if the connector could not be found.
00184      *
00185      * \param name the name. This can be a canonical name or the connector name.
00186      *
00187      * \return the connector or NULL if not found.
00188      */
00189     boost::shared_ptr< WModuleConnector > findConnector( std::string name );
00190 
00191     /**
00192      * Return a pointer to the properties object of the module.
00193      *
00194      * \return the properties.
00195      */
00196     boost::shared_ptr< WProperties > getProperties() const;
00197 
00198     /**
00199      * Return a pointer to the information properties object of the module. The module intends these properties to not be modified.
00200      *
00201      * \return the properties.
00202      */
00203     boost::shared_ptr< WProperties > getInformationProperties() const;
00204 
00205     /**
00206      * Determines whether the module instance is properly initialized.
00207      *
00208      * \return true if properly initialized.
00209      */
00210     const WBoolFlag& isInitialized() const;
00211 
00212     /**
00213      * Checks whether the module instance is ready to be used. This is the case if isInitialized && isAssociated.
00214      *
00215      * \return isInitialized && isAssociated
00216      */
00217     const WBoolFlag&  isUseable() const;
00218 
00219      /**
00220       * Checks whether this module is associated with an container.
00221       *
00222       * \return true if associated.
00223       */
00224     const WBoolFlag&  isAssociated() const;
00225 
00226      /**
00227       * Checks whether this module is ready.
00228       *
00229       * \return true if ready.
00230       */
00231     const WBoolFlag&  isReady() const;
00232 
00233     /**
00234      * Checks whether this module has been crashed. This will be true whenever the module throws an unhandled exception.
00235      *
00236      * \return true if there has been an exception during moduleMain().
00237      */
00238     const WBoolFlag& isCrashed() const;
00239 
00240     /**
00241      * 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
00242      * crashed before ready() got called, you most probably would wait endlessly.
00243      *
00244      * \return isReady || isCrashed.
00245      */
00246     const WBoolFlag& isReadyOrCrashed() const;
00247 
00248     /**
00249      * Returns a flag denoting whether the thread currently is running or nor. It is also useful to get a callback whenever a module stops.
00250      *
00251      * \return the flag
00252      */
00253     const WBoolFlag& isRunning() const;
00254 
00255      /**
00256       * The container this module is associated with.
00257       *
00258       * \return the container.
00259       */
00260     boost::shared_ptr< WModuleContainer > getAssociatedContainer() const;
00261 
00262     /**
00263      * Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it
00264      * should never be initialized or modified in some other way. A simple new instance is required.
00265      *
00266      * \return the prototype used to create every module in OpenWalnut.
00267      */
00268     virtual boost::shared_ptr< WModule > factory() const = 0;
00269 
00270     /**
00271      * Connects a specified notify function with a signal this module instance is offering.
00272      *
00273      * \exception WModuleSignalSubscriptionFailed thrown if the signal can't be connected.
00274      *
00275      * \param signal the signal to connect to.
00276      * \param notifier the notifier function to bind.
00277      *
00278      * \return connection descriptor.
00279      */
00280     virtual boost::signals2::connection subscribeSignal( MODULE_SIGNAL signal, t_ModuleGenericSignalHandlerType notifier );
00281 
00282     /**
00283      * Connects a specified notify function with a signal this module instance is offering.
00284      *
00285      * \exception WModuleSignalSubscriptionFailed thrown if the signal can't be connected.
00286      *
00287      * \param signal the signal to connect to.
00288      * \param notifier the notifier function to bind.
00289      *
00290      * \return connection descriptor.
00291      */
00292     virtual boost::signals2::connection subscribeSignal( MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier );
00293 
00294     /**
00295      * Gets the modules base progress. This is actually a progress combiner, which bundles all progresses.
00296      *
00297      * \return the progress combiner for this module.
00298      */
00299     virtual boost::shared_ptr< WProgressCombiner > getRootProgressCombiner();
00300 
00301     /**
00302      * Get the icon for this module in XPM format.
00303      * \return The icon.
00304      */
00305     virtual const char** getXPMIcon() const;
00306 
00307     /**
00308      * Gets the type of the module. This is useful for FAST differentiation between several modules like standard modules and data
00309      * modules which play a special role in OpenWalnut/Kernel.
00310      *
00311      * \return the Type. If you do not overwrite this method, it will return MODULE_ARBITRARY.
00312      */
00313     virtual MODULE_TYPE getType() const;
00314 
00315     /**
00316      * Completely disconnects all connected connectors of this module. This is useful to isolate a module (for deletion, removal from a container
00317      * and so on.)
00318      */
00319     void disconnect();
00320 
00321     /**
00322      * Gives a list of all WDisconnectCombiners possible. Please note that while the list exists, connections might change.
00323      *
00324      * \return the list of possible disconnect operations
00325      */
00326     WCombinerTypes::WDisconnectList getPossibleDisconnections();
00327 
00328     /**
00329      * Sets the local module path. This gets called by the module loader.
00330      *
00331      * \param path the local path.
00332      */
00333     void setLocalPath( boost::filesystem::path path );
00334 
00335     /**
00336      * Returns the local path of the module. Whenever you try to load local resources, use this path. It is especially useful for shader loading.
00337      *
00338      * \return the local module path.
00339      */
00340     boost::filesystem::path getLocalPath() const;
00341 
00342     /**
00343      * Checks whether the module was marked as deprecated.
00344      *
00345      * \return true if deprecated
00346      */
00347     bool isDeprecated() const;
00348 
00349     /**
00350      * Queries the deprecation message of a module if specified. If not specified, an empty string is returned. Check \ref isDeprecated first.
00351      *
00352      * \return deprecation message
00353      */
00354     std::string getDeprecationMessage() const;
00355 protected:
00356 
00357     /**
00358      * Entry point after loading the module. Runs in separate thread.
00359      */
00360     virtual void moduleMain() = 0;
00361 
00362     /**
00363      * Thread entry point. Calls moduleMain and sends error notification if needed.
00364      */
00365     void threadMain();
00366 
00367      /**
00368       * Sets the container this module is associated with.
00369       *
00370       * \param container the container to associate with.
00371       */
00372     void setAssociatedContainer( boost::shared_ptr< WModuleContainer > container );
00373 
00374     // **************************************************************************************************************************
00375     //
00376     // Connector Management
00377     //
00378     // **************************************************************************************************************************
00379 
00380     /**
00381      * Initialize connectors in this function. This function must not be called multiple times for one module instance.
00382      * The module container manages calling those functions -> so just implement it.
00383      */
00384     virtual void connectors();
00385 
00386     /**
00387      * Initialize properties in this function. This function must not be called multiple times for one module instance.
00388      * The module container manages calling those functions -> so just implement it. Once initialized the number and type
00389      * of all properties should be set.
00390      */
00391     virtual void properties();
00392 
00393     /**
00394      * Initialize requirements in this function. This function must not be called multiple times for one module instance.
00395      * The module should always implement this. Using this method, a module can tell the kernel what it needs to run properly. For example, it
00396      * can require a running graphics engine or, in the case of module containers, other modules.
00397      */
00398     virtual void requirements();
00399 
00400     /**
00401      * This function allows module programmers to mark their modules deprecated in a user-friendly way. If you implement this function, you need
00402      * to specify an text which should mention an alternative module.
00403      *
00404      * \note do not add sentences like "this module is deprecated" or similar, since the GUI the user is using already shows this message. The
00405      * message should say WHY it is deprecated and what alternative module is available.
00406      * \return deprecation message
00407      */
00408     virtual std::string deprecated() const;
00409 
00410     /**
00411      * Manages connector initialization. Gets called by module container.
00412      *
00413      * \throw WModuleConnectorInitFailed if called multiple times.
00414      */
00415     void initialize();
00416 
00417     /**
00418      * Called whenever the module should shutdown.
00419      */
00420     virtual void cleanup();
00421 
00422     /**
00423      * Adds the specified connector to the list of inputs.
00424      *
00425      * \param con the connector.
00426      */
00427     void addConnector( boost::shared_ptr<WModuleInputConnector> con );
00428 
00429     /**
00430      * Adds the specified connector to the list of outputs.
00431      *
00432      * \param con the connector.
00433      */
00434     void addConnector( boost::shared_ptr<WModuleOutputConnector> con );
00435 
00436     /**
00437      * Removes all connectors properly. It disconnects the connectors and cleans the connectors list.
00438      */
00439     void removeConnectors();
00440 
00441     /**
00442      * Callback for m_active. Overwrite this in your modules to handle m_active changes separately.
00443      */
00444     virtual void activate();
00445 
00446     // **************************************************************************************************************************
00447     //
00448     // Signal handlers that HAVE to be in every module. By default they do nothing. You should overwrite them to get notified
00449     // with the corresponding signal
00450     //
00451     // **************************************************************************************************************************
00452 
00453     /**
00454      * Gives the signal handler function responsible for a given signal. Modules defining own signal handlers should overwrite
00455      * this function. This function is protected since boost::functions are callable, which is what is not wanted here. Just
00456      * signals should call them.
00457      *
00458      * \param signal the signal to get the handler for.
00459      *
00460      * \return the signal handler for "signal".
00461      */
00462     virtual const t_GenericSignalHandlerType getSignalHandler( MODULE_CONNECTOR_SIGNAL signal );
00463 
00464     /**
00465      * Gets called whenever a connector gets connected to the specified input.
00466      *
00467      * \param here the connector of THIS module that got connected to "there"
00468      * \param there the connector that has been connected with the connector "here" of this module.
00469      */
00470     virtual void notifyConnectionEstablished( boost::shared_ptr<WModuleConnector> here,
00471                                               boost::shared_ptr<WModuleConnector> there );
00472     /**
00473      * Gets called whenever a connection between a remote and local connector gets closed.
00474      *
00475      * \param here the connector of THIS module getting disconnected.
00476      * \param there the connector of the other module getting disconnected.
00477      */
00478     virtual void notifyConnectionClosed( boost::shared_ptr<WModuleConnector> here, boost::shared_ptr<WModuleConnector> there );
00479 
00480     /**
00481      * Gets called when the data on one input connector changed.
00482      *
00483      * \param input the input connector receiving the change.
00484      * \param output the output connector sending the change notification.
00485      */
00486     virtual void notifyDataChange( boost::shared_ptr<WModuleConnector> input,
00487                                    boost::shared_ptr<WModuleConnector> output );
00488 
00489     /**
00490      * Call this whenever your module is ready and can react on property changes.
00491      */
00492     void ready();
00493 
00494     /**
00495      * Logger instance for comfortable info logging. Simply use logInfo() << "my info".
00496      *
00497      * \return the logger stream.
00498      */
00499     wlog::WStreamedLogger infoLog() const;
00500 
00501     /**
00502      * Logger instance for comfortable debug logging. Simply use logDebug() << "my debug".
00503      *
00504      * \return the logger stream.
00505      */
00506     wlog::WStreamedLogger debugLog() const;
00507 
00508     /**
00509      * Logger instance for comfortable warning- logs. Simply use logWarning() << "my warning".
00510      *
00511      * \return the logger stream.
00512      */
00513     wlog::WStreamedLogger warnLog() const;
00514 
00515     /**
00516      * Logger instance for comfortable error logging. Simply use logError() << "my error".
00517      *
00518      * \return the logger stream.
00519      */
00520     wlog::WStreamedLogger errorLog() const;
00521 
00522     // **************************************************************************************************************************
00523     //
00524     // Members
00525     //
00526     // **************************************************************************************************************************
00527 
00528     /**
00529      * The property object for the module.
00530      */
00531     boost::shared_ptr< WProperties > m_properties;
00532 
00533     /**
00534      * The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION". It is useful to define some property
00535      * 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
00536      * m_properties.
00537      */
00538     boost::shared_ptr< WProperties > m_infoProperties;
00539 
00540     /**
00541      * Progress indicator used as parent for all progress' of this module.
00542      */
00543     boost::shared_ptr< WProgressCombiner > m_progress;
00544 
00545     /**
00546      * True if everything is initialized and ready to be used.
00547      */
00548     WBoolFlag m_initialized;
00549 
00550     /**
00551      * True if container got associated with this flag.
00552      */
00553     WBoolFlag m_isAssociated;
00554 
00555     /**
00556      * True if associated && initialized.
00557      */
00558     WBoolFlag m_isUsable;
00559 
00560     /**
00561      * True if ready() was called.
00562      */
00563     WBoolFlag m_isReady;
00564 
00565     /**
00566      * True whenever an exception is thrown during moduleMain.
00567      */
00568     WBoolFlag m_isCrashed;
00569 
00570     /**
00571      * 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.
00572      */
00573     WBoolFlag m_isReadyOrCrashed;
00574 
00575     /**
00576      * True if the module currently is running.
00577      */
00578     WBoolFlag m_isRunning;
00579 
00580     /**
00581      * Progress indicator for the "ready" state.
00582      */
00583     boost::shared_ptr< WProgress > m_readyProgress;
00584 
00585     /**
00586      * The internal state of the module. This is, by default, simply the exit flag from WThreadedRunner.
00587      */
00588     WConditionSet m_moduleState;
00589 
00590     /**
00591      * The container this module belongs to.
00592      */
00593     boost::shared_ptr< WModuleContainer > m_container;
00594 
00595     /**
00596      * Set of input connectors associated with this module.
00597      */
00598     InputConnectorList m_inputConnectors;
00599 
00600     /**
00601      * Set of output connectors associated with this module.
00602      */
00603     OutputConnectorList m_outputConnectors;
00604 
00605     /**
00606      * True whenever the module should be active
00607      */
00608     WPropBool m_active;
00609 
00610     /**
00611      * This property holds a user specified name for the current module instance.
00612      */
00613     WPropString m_runtimeName;
00614 
00615     /**
00616      * 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
00617      * module loader. Use this to load shaders and so on.
00618      */
00619     boost::filesystem::path m_localPath;
00620 
00621     /**
00622      * The type of the requirement list.
00623      */
00624     typedef std::vector< WRequirement* > Requirements;
00625 
00626     /**
00627      * The list of requirements.
00628      */
00629     Requirements m_requirements;
00630 
00631 private:
00632 
00633      /**
00634      * Lock for m_inputConnectors.
00635      */
00636     // boost::shared_mutex m_inputConnectorsLock;
00637 
00638     /**
00639      * Lock for m_outputConnectors.
00640      */
00641     // boost::shared_mutex m_outputConnectorsLock;
00642 
00643     /**
00644      * Signal fired whenever a module main thread is ready.
00645      */
00646     t_ModuleGenericSignalType signal_ready;
00647 
00648     /**
00649      * Signal fired whenever a module main thread throws an exception/error.
00650      */
00651     t_ModuleErrorSignalType signal_error;
00652 
00653     /**
00654      * This method checks whether all the requirements of the module are complied.
00655      *
00656      * \return the requirement that has failed.
00657      */
00658     const WRequirement* checkRequirements() const;
00659 };
00660 
00661 /**
00662  * Simply a list of modules. The type is used by the following macros and typedefs
00663  */
00664 typedef std::vector< boost::shared_ptr< WModule > > WModuleList;
00665 
00666 /**
00667  * The signature used for the module loading entry point
00668  */
00669 typedef void ( *W_LOADABLE_MODULE_SIGNATURE )( WModuleList& );
00670 
00671 /**
00672  * The following macro is used by modules so the factory can acquire a prototype instance from a shared library using the symbol.
00673  * You can write this symbol for your own if you need to add multiple modules to the list. This one is for convenience.
00674  *
00675  * \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
00676  *       pointer causes segmentation faults during load.
00677  */
00678 #ifdef _MSC_VER
00679 #define W_LOADABLE_MODULE( MODULECLASS ) \
00680 extern "C" __declspec(dllexport) void WLoadModule( WModuleList& m ) { m.push_back( boost::shared_ptr< WModule >( new MODULECLASS ) ); }  // NOLINT
00681 #else
00682 #define W_LOADABLE_MODULE( MODULECLASS ) \
00683 extern "C"                       void WLoadModule( WModuleList& m ) { m.push_back( boost::shared_ptr< WModule >( new MODULECLASS ) ); }  // NOLINT
00684 #endif
00685 
00686 /**
00687  * The corresponding symbol name.
00688  */
00689 #define W_LOADABLE_MODULE_SYMBOL "WLoadModule"
00690 
00691 /**
00692  * \defgroup modules Modules
00693  *
00694  * \brief
00695  * This group contains modules of OpenWalnut.
00696  * The term modules can be understood as "plugin" or "algorithm" in this context.
00697  */
00698 #endif  // WMODULE_H
00699 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends