OpenWalnut 1.3.1
|
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 WMODULECONTAINER_H 00026 #define WMODULECONTAINER_H 00027 00028 #include <list> 00029 #include <map> 00030 #include <set> 00031 #include <string> 00032 #include <utility> 00033 #include <vector> 00034 00035 #include <boost/function.hpp> 00036 #include <boost/shared_ptr.hpp> 00037 #include <boost/signals2/signal.hpp> 00038 #include <boost/thread.hpp> 00039 00040 #include "../common/WSharedObject.h" 00041 00042 #include "WModule.h" 00043 #include "WModuleCombinerTypes.h" 00044 #include "WModuleConnectorSignals.h" 00045 #include "WModuleSignals.h" 00046 #include "WBatchLoader.h" 00047 00048 class WThreadedRunner; 00049 class WDataModule; 00050 00051 00052 00053 /** 00054 * Class able to contain other modules. It manages several tasks like finding appropriate modules, managing data modules and 00055 * module initialization. 00056 * 00057 * \ingroup Kernel 00058 */ 00059 class WModuleContainer: public WModule 00060 { 00061 public: 00062 // the following typedefs are for convenience; to help accessing the container in a thread safe way. 00063 00064 /** 00065 * A vector of modules 00066 */ 00067 typedef std::vector< boost::shared_ptr< WModule > > ModuleVectorType; 00068 00069 /** 00070 * For shortening: a type defining a shared vector of WModule pointers. 00071 */ 00072 typedef std::set< boost::shared_ptr< WModule > > ModuleContainerType; 00073 00074 /** 00075 * The alias for a shared container. 00076 */ 00077 typedef WSharedObject< ModuleContainerType > ModuleSharedContainerType; 00078 00079 /** 00080 * The const iterator type of the container. 00081 */ 00082 typedef ModuleContainerType::const_iterator ModuleConstIterator; 00083 00084 /** 00085 * The iterator type of the container. 00086 */ 00087 typedef ModuleContainerType::iterator ModuleIterator; 00088 00089 00090 /** 00091 * Constructor. Initializes container. 00092 * 00093 * \param name name of the container 00094 * \param description short description. 00095 */ 00096 WModuleContainer( std::string name = "Unnamed Module Container", 00097 std::string description = "Used as container for several modules." ); 00098 00099 /** 00100 * Destructor. 00101 */ 00102 virtual ~WModuleContainer(); 00103 00104 /** 00105 * Add a module to this container and start it. Please note, that a module can be added only once. If it already is 00106 * associated with this container nothing happens. 00107 * 00108 * \param module the module to add. 00109 * \param run true when the module should be run automatically after adding it. 00110 * \throw WModuleUninitialized thrown whenever someone wants to add a module not yet initialized. 00111 */ 00112 virtual void add( boost::shared_ptr< WModule > module, bool run = true ); 00113 00114 /** 00115 * Convenience method to create a module instance with a given name and automatically add it to the container. 00116 * 00117 * \param name the prototype name to create 00118 * 00119 * \return the created and added module 00120 */ 00121 virtual WModule::SPtr createAndAdd( std::string name ); 00122 00123 /** 00124 * Remove the given module from this container if it is associated with it. It only provides flat removal. It does not remove depending 00125 * modules. Please be aware that this method does NOT stop the module. It just removes it from the container. If you release the shared 00126 * pointer after removing from the container, the instance gets freed although it still might run. To also wait for the module to quit, use 00127 * module->wait( true ). 00128 * 00129 * \param module the module to remove. 00130 */ 00131 virtual void remove( boost::shared_ptr< WModule > module ); 00132 00133 /** 00134 * Stops all modules inside this container. Note that this function could take some time, since it waits until the last module 00135 * has quit. 00136 */ 00137 virtual void stop(); 00138 00139 /** 00140 * Gives back the name of this module. 00141 * \return the module's name. 00142 */ 00143 virtual const std::string getName() const; 00144 00145 /** 00146 * Gives back a description of this module. 00147 * \return description to module. 00148 */ 00149 virtual const std::string getDescription() const; 00150 00151 /** 00152 * Add a specified notifier to the list of default notifiers which get connected to each added module. 00153 * 00154 * \param signal the signal the notifier should get connected to 00155 * \param notifier the notifier function 00156 */ 00157 virtual void addDefaultNotifier( MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier ); 00158 00159 /** 00160 * Add a specified notifier to the list of default notifiers which get connected to each added module. 00161 * 00162 * \param signal the signal the notifier should get connected to 00163 * \param notifier the notifier function 00164 */ 00165 virtual void addDefaultNotifier( MODULE_SIGNAL signal, t_ModuleGenericSignalHandlerType notifier ); 00166 00167 /** 00168 * Add a specified notifier to the list of default notifiers which get connected to each added module. This is especially used for all the 00169 * connector related events like connect and disconnect. 00170 * \note This signal is only called for input connectors! 00171 * 00172 * \param signal the signal the notifier should get connected to 00173 * \param notifier the notifier function 00174 */ 00175 virtual void addDefaultNotifier( MODULE_CONNECTOR_SIGNAL signal, t_GenericSignalHandlerType notifier ); 00176 00177 /** 00178 * Function combines two modules. This runs synchronously. It might take some time to finish since combination of modules is 00179 * allowed only with modules marked as "ready" which might take some time. 00180 * 00181 * \param applyOn the module which already has to be in the container and to apply the other one on. 00182 * \param what the prototype name of the module to apply on the other one specified. 00183 * \param tryOnly If set to false and the prototype "what" does not exist this will throw an exception. If set to true and the prototype does 00184 * not exist, the nothing will happen. 00185 * 00186 * \return the newly created module connected with the one specified in applyOn. If the prototype could not be found and tryOnly was set to 00187 * true it will return NULL. 00188 */ 00189 virtual boost::shared_ptr< WModule > applyModule( boost::shared_ptr< WModule > applyOn, std::string what, bool tryOnly = false ); 00190 00191 /** 00192 * Function combines two modules. This runs synchronously. It might take some time to finish since combination of modules is 00193 * allowed only with modules marked as "ready" which might take some time. 00194 * 00195 * \param applyOn the module which already has to be in the container and to apply the other one on. 00196 * \param prototype the prototype of the module to apply on the other one specified. 00197 * 00198 * \return the newly created module connected with the one specified in applyOn. 00199 */ 00200 virtual boost::shared_ptr< WModule > applyModule( boost::shared_ptr< WModule > applyOn, boost::shared_ptr< WModule > prototype ); 00201 00202 /** 00203 * Load specified datasets. It immediately returns and starts another thread, which actually loads the data. 00204 * 00205 * \param filenames list of filenames to load. The registered notification handler for the root container will get notified on 00206 * error and success. 00207 * \param suppressColormaps if true, the data modules are instructed to avoid registration of colormaps. This can be very handy if you 00208 * combine multiple data loaders into one new data loader or data set 00209 * 00210 * \return the loader handling the load operation 00211 */ 00212 WBatchLoader::SPtr loadDataSets( std::vector< std::string > filenames, bool suppressColormaps = false ); 00213 00214 /** 00215 * Loads the specified files synchronously. The returned batchloader can be queried for the list of data modules that have been added. 00216 * 00217 * \param filenames list of filenames to load. The registered notification handler for the root container will get notified on 00218 * error and success. 00219 * \param suppressColormaps if true, the data modules are instructed to avoid registration of colormaps. This can be very handy if you 00220 * combine multiple data loaders into one new data loader or data set 00221 * 00222 * \return the loader has handled the load operation 00223 */ 00224 WBatchLoader::SPtr loadDataSetsSynchronously( std::vector< std::string > filenames, bool suppressColormaps = false ); 00225 00226 /** 00227 * Add the specified thread to the list of pending jobs. Only this ensures, that ALL pending threads get stopped before the 00228 * container gets stopped. 00229 * 00230 * \note use this to register threads whenever you start threads belonging to this container. This avoids shutting down the 00231 * container while other threads depend upon it. 00232 * 00233 * \param thread the thread to add 00234 */ 00235 void addPendingThread( boost::shared_ptr< WThreadedRunner > thread ); 00236 00237 /** 00238 * The specified thread has finished and does not longer depend upon this container instance. 00239 * 00240 * \param thread the thread. 00241 */ 00242 void finishedPendingThread( boost::shared_ptr< WThreadedRunner > thread ); 00243 00244 /** 00245 * Sets a flag denoting whether the container (which also is a module) should be marked as "crashed" if a nested module crashes. 00246 * 00247 * \param crashIfCrashed true if it also should crash. 00248 */ 00249 void setCrashIfModuleCrashes( bool crashIfCrashed = true ); 00250 00251 /** 00252 * Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it 00253 * should never be initialized or modified in some other way. A simple new instance is required. 00254 * 00255 * \return the prototype used to create every module in OpenWalnut. 00256 */ 00257 virtual boost::shared_ptr< WModule > factory() const; 00258 00259 /** 00260 * Simple type for WDataModule pointer lists. 00261 */ 00262 typedef std::set< boost::shared_ptr< WDataModule > > DataModuleListType; 00263 00264 /** 00265 * Returns a vector of pointers to the loaded data modules in the container. 00266 * 00267 * \return the list of data modules. 00268 */ 00269 DataModuleListType getDataModules(); 00270 00271 /** 00272 * Method returns a read ticket allowing read-access to the list of modules inside the container. 00273 * \note If done, ensure the ticket gets destroyed. 00274 * 00275 * \return the read ticket. 00276 */ 00277 ModuleSharedContainerType::ReadTicket getModules() const; 00278 00279 /** 00280 * Queries the container to find all modules with a given name. This can be useful to check for existence of certain modules inside the 00281 * container. 00282 * 00283 * \param name name of the modules to find 00284 * 00285 * \return the vector of modules. Empty if nothing was found. 00286 */ 00287 ModuleVectorType getModules( std::string name ) const; 00288 00289 /** 00290 * This method creates a list of combiner instances, for each possible connection that can be made between the specified module and the 00291 * module currently inside the container. It might be possible that a module which is contained in the returned list is not associated 00292 * anymore if the combiner gets applied. 00293 * 00294 * \param module the module to which the possible connections should be returned 00295 * 00296 * \return the possible combinations of connectors. 00297 */ 00298 WCombinerTypes::WCompatiblesList getPossibleConnections( boost::shared_ptr< WModule > module ); 00299 00300 protected: 00301 /** 00302 * Entry point after loading the module. Runs in separate thread. The module container does not use this method. It simply 00303 * returns. 00304 */ 00305 virtual void moduleMain(); 00306 00307 /** 00308 * The modules associated with this container. 00309 */ 00310 ModuleSharedContainerType m_modules; 00311 00312 /** 00313 * Name of the module. 00314 */ 00315 std::string m_name; 00316 00317 /** 00318 * Description of the module. 00319 */ 00320 std::string m_description; 00321 00322 /** 00323 * Lock for error notifiers set. 00324 */ 00325 boost::shared_mutex m_errorNotifiersLock; 00326 00327 /** 00328 * The error notifiers connected to added modules by default. 00329 */ 00330 std::list< t_ModuleErrorSignalHandlerType > m_errorNotifiers; 00331 00332 /** 00333 * Lock for ready notifiers set. 00334 */ 00335 boost::shared_mutex m_readyNotifiersLock; 00336 00337 /** 00338 * The ready notifiers connected to added modules by default. 00339 */ 00340 std::list< t_ModuleGenericSignalHandlerType > m_readyNotifiers; 00341 00342 /** 00343 * Lock for associated notifiers set. 00344 */ 00345 boost::shared_mutex m_associatedNotifiersLock; 00346 00347 /** 00348 * The notifiers connected to added modules by default and fired whenever the module got associated. 00349 */ 00350 std::list< t_ModuleGenericSignalHandlerType > m_associatedNotifiers; 00351 00352 /** 00353 * Lock for remove-notifiers set. 00354 */ 00355 boost::shared_mutex m_removedNotifiersLock; 00356 00357 /** 00358 * The notifiers connected to added modules by default and fired whenever the module got removed again. 00359 */ 00360 std::list< t_ModuleGenericSignalHandlerType > m_removedNotifiers; 00361 00362 /** 00363 * Lock for connector-notifiers set. 00364 */ 00365 boost::shared_mutex m_connectorNotifiersLock; 00366 00367 /** 00368 * The notifiers connected to added modules by default and fired whenever the module connectors got connected. 00369 */ 00370 std::list< t_GenericSignalHandlerType > m_connectorEstablishedNotifiers; 00371 00372 /** 00373 * The notifiers connected to added modules by default and fired whenever the module connectors got disconnected. 00374 */ 00375 std::list< t_GenericSignalHandlerType > m_connectorClosedNotifiers; 00376 00377 /** 00378 * Set of all threads that currently depend upon this container. 00379 */ 00380 std::set< boost::shared_ptr< WThreadedRunner > > m_pendingThreads; 00381 00382 /** 00383 * Lock for m_pendingThreads. 00384 */ 00385 boost::shared_mutex m_pendingThreadsLock; 00386 00387 /** 00388 * This method is called whenever a module inside the container crashes. By default, this method does nothing but forwarding the using 00389 * WModule's signals. 00390 * 00391 * \param module the module that has crashed. 00392 * \param exception the exception. 00393 */ 00394 virtual void moduleError( boost::shared_ptr< WModule > module, const WException& exception ); 00395 00396 /** 00397 * This flag denotes whether the whole container should be marked as crashed if one of the contained modules crashes. By default, this is 00398 * true. The root container (the container not nested in any other container) sets this to false explicitly. Modules using the container to 00399 * encapsulate a whole bunch of modules can decide, but by default they crash too. 00400 */ 00401 bool m_crashIfModuleCrashes; 00402 00403 private: 00404 // the following typedefs are for convenience; to help accessing the container in a thread safe way. 00405 00406 /** 00407 * A type for mapping a module to all its subscriptions 00408 */ 00409 typedef std::pair< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscription; 00410 00411 /** 00412 * For shortening: a type defining a shared vector of subscriptions a module made to a notifier during add(). 00413 */ 00414 typedef std::multimap< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscriptionsType; 00415 00416 /** 00417 * The alias for a shared container. 00418 */ 00419 typedef WSharedObject< ModuleSubscriptionsType > ModuleSubscriptionsSharedType; 00420 00421 /** 00422 * The const iterator type of the container. 00423 */ 00424 typedef ModuleSubscriptionsType::const_iterator ModuleSubscriptionsConstIterator; 00425 00426 /** 00427 * The iterator type of the container. 00428 */ 00429 typedef ModuleSubscriptionsType::iterator ModuleSubscriptionsIterator; 00430 00431 /** 00432 * The module's signal subscriptions. 00433 */ 00434 ModuleSubscriptionsSharedType m_moduleSubscriptions; 00435 }; 00436 00437 #endif // WMODULECONTAINER_H 00438