OpenWalnut
1.4.0
|
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 * Removes all modules from this container. It uses a relatively laborious iterative approach 00135 * becausewe can not delete modules recursively so far. 00136 */ 00137 virtual void removeAll(); 00138 00139 /** 00140 * Stops all modules inside this container. Note that this function could take some time, since it waits until the last module 00141 * has quit. 00142 */ 00143 virtual void stop(); 00144 00145 /** 00146 * Gives back the name of this module. 00147 * \return the module's name. 00148 */ 00149 virtual const std::string getName() const; 00150 00151 /** 00152 * Gives back a description of this module. 00153 * \return description to module. 00154 */ 00155 virtual const std::string getDescription() const; 00156 00157 /** 00158 * Add a specified notifier to the list of default notifiers which get connected to each added module. 00159 * 00160 * \param signal the signal the notifier should get connected to 00161 * \param notifier the notifier function 00162 */ 00163 virtual void addDefaultNotifier( MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier ); 00164 00165 /** 00166 * Add a specified notifier to the list of default notifiers which get connected to each added module. 00167 * 00168 * \param signal the signal the notifier should get connected to 00169 * \param notifier the notifier function 00170 */ 00171 virtual void addDefaultNotifier( MODULE_SIGNAL signal, t_ModuleGenericSignalHandlerType notifier ); 00172 00173 /** 00174 * Add a specified notifier to the list of default notifiers which get connected to each added module. This is especially used for all the 00175 * connector related events like connect and disconnect. 00176 * \note This signal is only called for input connectors! 00177 * 00178 * \param signal the signal the notifier should get connected to 00179 * \param notifier the notifier function 00180 */ 00181 virtual void addDefaultNotifier( MODULE_CONNECTOR_SIGNAL signal, t_GenericSignalHandlerType notifier ); 00182 00183 /** 00184 * Function combines two modules. This runs synchronously. It might take some time to finish since combination of modules is 00185 * allowed only with modules marked as "ready" which might take some time. 00186 * 00187 * \param applyOn the module which already has to be in the container and to apply the other one on. 00188 * \param what the prototype name of the module to apply on the other one specified. 00189 * \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 00190 * not exist, the nothing will happen. 00191 * 00192 * \return the newly created module connected with the one specified in applyOn. If the prototype could not be found and tryOnly was set to 00193 * true it will return NULL. 00194 */ 00195 virtual boost::shared_ptr< WModule > applyModule( boost::shared_ptr< WModule > applyOn, std::string what, bool tryOnly = false ); 00196 00197 /** 00198 * Function combines two modules. This runs synchronously. It might take some time to finish since combination of modules is 00199 * allowed only with modules marked as "ready" which might take some time. 00200 * 00201 * \param applyOn the module which already has to be in the container and to apply the other one on. 00202 * \param prototype the prototype of the module to apply on the other one specified. 00203 * 00204 * \return the newly created module connected with the one specified in applyOn. 00205 */ 00206 virtual boost::shared_ptr< WModule > applyModule( boost::shared_ptr< WModule > applyOn, boost::shared_ptr< WModule > prototype ); 00207 00208 /** 00209 * Load specified datasets. It immediately returns and starts another thread, which actually loads the data. 00210 * 00211 * \param filenames list of filenames to load. The registered notification handler for the root container will get notified on 00212 * error and success. 00213 * \param suppressColormaps if true, the data modules are instructed to avoid registration of colormaps. This can be very handy if you 00214 * combine multiple data loaders into one new data loader or data set 00215 * 00216 * \return the loader handling the load operation 00217 */ 00218 WBatchLoader::SPtr loadDataSets( std::vector< std::string > filenames, bool suppressColormaps = false ); 00219 00220 /** 00221 * Loads the specified files synchronously. The returned batchloader can be queried for the list of data modules that have been added. 00222 * 00223 * \param filenames list of filenames to load. The registered notification handler for the root container will get notified on 00224 * error and success. 00225 * \param suppressColormaps if true, the data modules are instructed to avoid registration of colormaps. This can be very handy if you 00226 * combine multiple data loaders into one new data loader or data set 00227 * 00228 * \return the loader has handled the load operation 00229 */ 00230 WBatchLoader::SPtr loadDataSetsSynchronously( std::vector< std::string > filenames, bool suppressColormaps = false ); 00231 00232 /** 00233 * Add the specified thread to the list of pending jobs. Only this ensures, that ALL pending threads get stopped before the 00234 * container gets stopped. 00235 * 00236 * \note use this to register threads whenever you start threads belonging to this container. This avoids shutting down the 00237 * container while other threads depend upon it. 00238 * 00239 * \param thread the thread to add 00240 */ 00241 void addPendingThread( boost::shared_ptr< WThreadedRunner > thread ); 00242 00243 /** 00244 * The specified thread has finished and does not longer depend upon this container instance. 00245 * 00246 * \param thread the thread. 00247 */ 00248 void finishedPendingThread( boost::shared_ptr< WThreadedRunner > thread ); 00249 00250 /** 00251 * Sets a flag denoting whether the container (which also is a module) should be marked as "crashed" if a nested module crashes. 00252 * 00253 * \param crashIfCrashed true if it also should crash. 00254 */ 00255 void setCrashIfModuleCrashes( bool crashIfCrashed = true ); 00256 00257 /** 00258 * Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it 00259 * should never be initialized or modified in some other way. A simple new instance is required. 00260 * 00261 * \return the prototype used to create every module in OpenWalnut. 00262 */ 00263 virtual boost::shared_ptr< WModule > factory() const; 00264 00265 /** 00266 * Simple type for WDataModule pointer lists. 00267 */ 00268 typedef std::set< boost::shared_ptr< WDataModule > > DataModuleListType; 00269 00270 /** 00271 * Returns a vector of pointers to the loaded data modules in the container. 00272 * 00273 * \return the list of data modules. 00274 */ 00275 DataModuleListType getDataModules(); 00276 00277 /** 00278 * Method returns a read ticket allowing read-access to the list of modules inside the container. 00279 * \note If done, ensure the ticket gets destroyed. 00280 * 00281 * \return the read ticket. 00282 */ 00283 ModuleSharedContainerType::ReadTicket getModules() const; 00284 00285 /** 00286 * Queries the container to find all modules with a given name. This can be useful to check for existence of certain modules inside the 00287 * container. 00288 * 00289 * \param name name of the modules to find 00290 * 00291 * \return the vector of modules. Empty if nothing was found. 00292 */ 00293 ModuleVectorType getModules( std::string name ) const; 00294 00295 /** 00296 * This method creates a list of combiner instances, for each possible connection that can be made between the specified module and the 00297 * module currently inside the container. It might be possible that a module which is contained in the returned list is not associated 00298 * anymore if the combiner gets applied. 00299 * 00300 * \param module the module to which the possible connections should be returned 00301 * 00302 * \return the possible combinations of connectors. 00303 */ 00304 WCombinerTypes::WCompatiblesList getPossibleConnections( boost::shared_ptr< WModule > module ); 00305 00306 protected: 00307 /** 00308 * Entry point after loading the module. Runs in separate thread. The module container does not use this method. It simply 00309 * returns. 00310 */ 00311 virtual void moduleMain(); 00312 00313 /** 00314 * The modules associated with this container. 00315 */ 00316 ModuleSharedContainerType m_modules; 00317 00318 /** 00319 * Name of the module. 00320 */ 00321 std::string m_name; 00322 00323 /** 00324 * Description of the module. 00325 */ 00326 std::string m_description; 00327 00328 /** 00329 * Lock for error notifiers set. 00330 */ 00331 boost::shared_mutex m_errorNotifiersLock; 00332 00333 /** 00334 * The error notifiers connected to added modules by default. 00335 */ 00336 std::list< t_ModuleErrorSignalHandlerType > m_errorNotifiers; 00337 00338 /** 00339 * Lock for ready notifiers set. 00340 */ 00341 boost::shared_mutex m_readyNotifiersLock; 00342 00343 /** 00344 * The ready notifiers connected to added modules by default. 00345 */ 00346 std::list< t_ModuleGenericSignalHandlerType > m_readyNotifiers; 00347 00348 /** 00349 * Lock for associated notifiers set. 00350 */ 00351 boost::shared_mutex m_associatedNotifiersLock; 00352 00353 /** 00354 * The notifiers connected to added modules by default and fired whenever the module got associated. 00355 */ 00356 std::list< t_ModuleGenericSignalHandlerType > m_associatedNotifiers; 00357 00358 /** 00359 * Lock for remove-notifiers set. 00360 */ 00361 boost::shared_mutex m_removedNotifiersLock; 00362 00363 /** 00364 * The notifiers connected to added modules by default and fired whenever the module got removed again. 00365 */ 00366 std::list< t_ModuleGenericSignalHandlerType > m_removedNotifiers; 00367 00368 /** 00369 * Lock for connector-notifiers set. 00370 */ 00371 boost::shared_mutex m_connectorNotifiersLock; 00372 00373 /** 00374 * The notifiers connected to added modules by default and fired whenever the module connectors got connected. 00375 */ 00376 std::list< t_GenericSignalHandlerType > m_connectorEstablishedNotifiers; 00377 00378 /** 00379 * The notifiers connected to added modules by default and fired whenever the module connectors got disconnected. 00380 */ 00381 std::list< t_GenericSignalHandlerType > m_connectorClosedNotifiers; 00382 00383 /** 00384 * Set of all threads that currently depend upon this container. 00385 */ 00386 std::set< boost::shared_ptr< WThreadedRunner > > m_pendingThreads; 00387 00388 /** 00389 * Lock for m_pendingThreads. 00390 */ 00391 boost::shared_mutex m_pendingThreadsLock; 00392 00393 /** 00394 * This method is called whenever a module inside the container crashes. By default, this method does nothing but forwarding the using 00395 * WModule's signals. 00396 * 00397 * \param module the module that has crashed. 00398 * \param exception the exception. 00399 */ 00400 virtual void moduleError( boost::shared_ptr< WModule > module, const WException& exception ); 00401 00402 /** 00403 * This flag denotes whether the whole container should be marked as crashed if one of the contained modules crashes. By default, this is 00404 * true. The root container (the container not nested in any other container) sets this to false explicitly. Modules using the container to 00405 * encapsulate a whole bunch of modules can decide, but by default they crash too. 00406 */ 00407 bool m_crashIfModuleCrashes; 00408 00409 private: 00410 // the following typedefs are for convenience; to help accessing the container in a thread safe way. 00411 00412 /** 00413 * A type for mapping a module to all its subscriptions 00414 */ 00415 typedef std::pair< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscription; 00416 00417 /** 00418 * For shortening: a type defining a shared vector of subscriptions a module made to a notifier during add(). 00419 */ 00420 typedef std::multimap< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscriptionsType; 00421 00422 /** 00423 * The alias for a shared container. 00424 */ 00425 typedef WSharedObject< ModuleSubscriptionsType > ModuleSubscriptionsSharedType; 00426 00427 /** 00428 * The const iterator type of the container. 00429 */ 00430 typedef ModuleSubscriptionsType::const_iterator ModuleSubscriptionsConstIterator; 00431 00432 /** 00433 * The iterator type of the container. 00434 */ 00435 typedef ModuleSubscriptionsType::iterator ModuleSubscriptionsIterator; 00436 00437 /** 00438 * The module's signal subscriptions. 00439 */ 00440 ModuleSubscriptionsSharedType m_moduleSubscriptions; 00441 }; 00442 00443 #endif // WMODULECONTAINER_H 00444