OpenWalnut 1.2.5
|
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