OpenWalnut  1.4.0
WModuleContainer.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 WMODULECONTAINER_H
26 #define WMODULECONTAINER_H
27 
28 #include <list>
29 #include <map>
30 #include <set>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 #ifndef Q_MOC_RUN
36 #include <boost/function.hpp>
37 #endif
38 #ifndef Q_MOC_RUN
39 #include <boost/shared_ptr.hpp>
40 #endif
41 #ifndef Q_MOC_RUN
42 #include <boost/signals2/signal.hpp>
43 #endif
44 #ifndef Q_MOC_RUN
45 #include <boost/thread.hpp>
46 #endif
47 
48 #include "../common/WSharedObject.h"
49 
50 #include "WModule.h"
51 #include "WModuleCombinerTypes.h"
52 #include "WModuleConnectorSignals.h"
53 #include "WModuleSignals.h"
54 #include "WBatchLoader.h"
55 
56 class WThreadedRunner;
57 class WDataModule;
58 
59 
60 
61 /**
62  * Class able to contain other modules. It manages several tasks like finding appropriate modules, managing data modules and
63  * module initialization.
64  *
65  * \ingroup Kernel
66  */
68 {
69 public:
70  // the following typedefs are for convenience; to help accessing the container in a thread safe way.
71 
72  /**
73  * A vector of modules
74  */
75  typedef std::vector< boost::shared_ptr< WModule > > ModuleVectorType;
76 
77  /**
78  * For shortening: a type defining a shared vector of WModule pointers.
79  */
80  typedef std::set< boost::shared_ptr< WModule > > ModuleContainerType;
81 
82  /**
83  * The alias for a shared container.
84  */
86 
87  /**
88  * The const iterator type of the container.
89  */
90  typedef ModuleContainerType::const_iterator ModuleConstIterator;
91 
92  /**
93  * The iterator type of the container.
94  */
95  typedef ModuleContainerType::iterator ModuleIterator;
96 
97 
98  /**
99  * Constructor. Initializes container.
100  *
101  * \param name name of the container
102  * \param description short description.
103  */
104  WModuleContainer( std::string name = "Unnamed Module Container",
105  std::string description = "Used as container for several modules." );
106 
107  /**
108  * Destructor.
109  */
110  virtual ~WModuleContainer();
111 
112  /**
113  * Add a module to this container and start it. Please note, that a module can be added only once. If it already is
114  * associated with this container nothing happens.
115  *
116  * \param module the module to add.
117  * \param run true when the module should be run automatically after adding it.
118  * \throw WModuleUninitialized thrown whenever someone wants to add a module not yet initialized.
119  */
120  virtual void add( boost::shared_ptr< WModule > module, bool run = true );
121 
122  /**
123  * Convenience method to create a module instance with a given name and automatically add it to the container.
124  *
125  * \param name the prototype name to create
126  *
127  * \return the created and added module
128  */
129  virtual WModule::SPtr createAndAdd( std::string name );
130 
131  /**
132  * Remove the given module from this container if it is associated with it. It only provides flat removal. It does not remove depending
133  * modules. Please be aware that this method does NOT stop the module. It just removes it from the container. If you release the shared
134  * pointer after removing from the container, the instance gets freed although it still might run. To also wait for the module to quit, use
135  * module->wait( true ).
136  *
137  * \param module the module to remove.
138  */
139  virtual void remove( boost::shared_ptr< WModule > module );
140 
141  /**
142  * Removes all modules from this container. It uses a relatively laborious iterative approach
143  * becausewe can not delete modules recursively so far.
144  */
145  virtual void removeAll();
146 
147  /**
148  * Stops all modules inside this container. Note that this function could take some time, since it waits until the last module
149  * has quit.
150  */
151  virtual void stop();
152 
153  /**
154  * Gives back the name of this module.
155  * \return the module's name.
156  */
157  virtual const std::string getName() const;
158 
159  /**
160  * Gives back a description of this module.
161  * \return description to module.
162  */
163  virtual const std::string getDescription() const;
164 
165  /**
166  * Add a specified notifier to the list of default notifiers which get connected to each added module.
167  *
168  * \param signal the signal the notifier should get connected to
169  * \param notifier the notifier function
170  */
171  virtual void addDefaultNotifier( MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier );
172 
173  /**
174  * Add a specified notifier to the list of default notifiers which get connected to each added module.
175  *
176  * \param signal the signal the notifier should get connected to
177  * \param notifier the notifier function
178  */
179  virtual void addDefaultNotifier( MODULE_SIGNAL signal, t_ModuleGenericSignalHandlerType notifier );
180 
181  /**
182  * Add a specified notifier to the list of default notifiers which get connected to each added module. This is especially used for all the
183  * connector related events like connect and disconnect.
184  * \note This signal is only called for input connectors!
185  *
186  * \param signal the signal the notifier should get connected to
187  * \param notifier the notifier function
188  */
189  virtual void addDefaultNotifier( MODULE_CONNECTOR_SIGNAL signal, t_GenericSignalHandlerType notifier );
190 
191  /**
192  * Function combines two modules. This runs synchronously. It might take some time to finish since combination of modules is
193  * allowed only with modules marked as "ready" which might take some time.
194  *
195  * \param applyOn the module which already has to be in the container and to apply the other one on.
196  * \param what the prototype name of the module to apply on the other one specified.
197  * \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
198  * not exist, the nothing will happen.
199  *
200  * \return the newly created module connected with the one specified in applyOn. If the prototype could not be found and tryOnly was set to
201  * true it will return NULL.
202  */
203  virtual boost::shared_ptr< WModule > applyModule( boost::shared_ptr< WModule > applyOn, std::string what, bool tryOnly = false );
204 
205  /**
206  * Function combines two modules. This runs synchronously. It might take some time to finish since combination of modules is
207  * allowed only with modules marked as "ready" which might take some time.
208  *
209  * \param applyOn the module which already has to be in the container and to apply the other one on.
210  * \param prototype the prototype of the module to apply on the other one specified.
211  *
212  * \return the newly created module connected with the one specified in applyOn.
213  */
214  virtual boost::shared_ptr< WModule > applyModule( boost::shared_ptr< WModule > applyOn, boost::shared_ptr< WModule > prototype );
215 
216  /**
217  * Load specified datasets. It immediately returns and starts another thread, which actually loads the data.
218  *
219  * \param filenames list of filenames to load. The registered notification handler for the root container will get notified on
220  * error and success.
221  * \param suppressColormaps if true, the data modules are instructed to avoid registration of colormaps. This can be very handy if you
222  * combine multiple data loaders into one new data loader or data set
223  *
224  * \return the loader handling the load operation
225  */
226  WBatchLoader::SPtr loadDataSets( std::vector< std::string > filenames, bool suppressColormaps = false );
227 
228  /**
229  * Loads the specified files synchronously. The returned batchloader can be queried for the list of data modules that have been added.
230  *
231  * \param filenames list of filenames to load. The registered notification handler for the root container will get notified on
232  * error and success.
233  * \param suppressColormaps if true, the data modules are instructed to avoid registration of colormaps. This can be very handy if you
234  * combine multiple data loaders into one new data loader or data set
235  *
236  * \return the loader has handled the load operation
237  */
238  WBatchLoader::SPtr loadDataSetsSynchronously( std::vector< std::string > filenames, bool suppressColormaps = false );
239 
240  /**
241  * Add the specified thread to the list of pending jobs. Only this ensures, that ALL pending threads get stopped before the
242  * container gets stopped.
243  *
244  * \note use this to register threads whenever you start threads belonging to this container. This avoids shutting down the
245  * container while other threads depend upon it.
246  *
247  * \param thread the thread to add
248  */
249  void addPendingThread( boost::shared_ptr< WThreadedRunner > thread );
250 
251  /**
252  * The specified thread has finished and does not longer depend upon this container instance.
253  *
254  * \param thread the thread.
255  */
256  void finishedPendingThread( boost::shared_ptr< WThreadedRunner > thread );
257 
258  /**
259  * Sets a flag denoting whether the container (which also is a module) should be marked as "crashed" if a nested module crashes.
260  *
261  * \param crashIfCrashed true if it also should crash.
262  */
263  void setCrashIfModuleCrashes( bool crashIfCrashed = true );
264 
265  /**
266  * Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it
267  * should never be initialized or modified in some other way. A simple new instance is required.
268  *
269  * \return the prototype used to create every module in OpenWalnut.
270  */
271  virtual boost::shared_ptr< WModule > factory() const;
272 
273  /**
274  * Simple type for WDataModule pointer lists.
275  */
276  typedef std::set< boost::shared_ptr< WDataModule > > DataModuleListType;
277 
278  /**
279  * Returns a vector of pointers to the loaded data modules in the container.
280  *
281  * \return the list of data modules.
282  */
283  DataModuleListType getDataModules();
284 
285  /**
286  * Method returns a read ticket allowing read-access to the list of modules inside the container.
287  * \note If done, ensure the ticket gets destroyed.
288  *
289  * \return the read ticket.
290  */
292 
293  /**
294  * Queries the container to find all modules with a given name. This can be useful to check for existence of certain modules inside the
295  * container.
296  *
297  * \param name name of the modules to find
298  *
299  * \return the vector of modules. Empty if nothing was found.
300  */
301  ModuleVectorType getModules( std::string name ) const;
302 
303  /**
304  * This method creates a list of combiner instances, for each possible connection that can be made between the specified module and the
305  * module currently inside the container. It might be possible that a module which is contained in the returned list is not associated
306  * anymore if the combiner gets applied.
307  *
308  * \param module the module to which the possible connections should be returned
309  *
310  * \return the possible combinations of connectors.
311  */
312  WCombinerTypes::WCompatiblesList getPossibleConnections( boost::shared_ptr< WModule > module );
313 
314 protected:
315  /**
316  * Entry point after loading the module. Runs in separate thread. The module container does not use this method. It simply
317  * returns.
318  */
319  virtual void moduleMain();
320 
321  /**
322  * The modules associated with this container.
323  */
324  ModuleSharedContainerType m_modules;
325 
326  /**
327  * Name of the module.
328  */
329  std::string m_name;
330 
331  /**
332  * Description of the module.
333  */
334  std::string m_description;
335 
336  /**
337  * Lock for error notifiers set.
338  */
339  boost::shared_mutex m_errorNotifiersLock;
340 
341  /**
342  * The error notifiers connected to added modules by default.
343  */
344  std::list< t_ModuleErrorSignalHandlerType > m_errorNotifiers;
345 
346  /**
347  * Lock for ready notifiers set.
348  */
349  boost::shared_mutex m_readyNotifiersLock;
350 
351  /**
352  * The ready notifiers connected to added modules by default.
353  */
354  std::list< t_ModuleGenericSignalHandlerType > m_readyNotifiers;
355 
356  /**
357  * Lock for associated notifiers set.
358  */
359  boost::shared_mutex m_associatedNotifiersLock;
360 
361  /**
362  * The notifiers connected to added modules by default and fired whenever the module got associated.
363  */
364  std::list< t_ModuleGenericSignalHandlerType > m_associatedNotifiers;
365 
366  /**
367  * Lock for remove-notifiers set.
368  */
369  boost::shared_mutex m_removedNotifiersLock;
370 
371  /**
372  * The notifiers connected to added modules by default and fired whenever the module got removed again.
373  */
374  std::list< t_ModuleGenericSignalHandlerType > m_removedNotifiers;
375 
376  /**
377  * Lock for connector-notifiers set.
378  */
379  boost::shared_mutex m_connectorNotifiersLock;
380 
381  /**
382  * The notifiers connected to added modules by default and fired whenever the module connectors got connected.
383  */
384  std::list< t_GenericSignalHandlerType > m_connectorEstablishedNotifiers;
385 
386  /**
387  * The notifiers connected to added modules by default and fired whenever the module connectors got disconnected.
388  */
389  std::list< t_GenericSignalHandlerType > m_connectorClosedNotifiers;
390 
391  /**
392  * Set of all threads that currently depend upon this container.
393  */
394  std::set< boost::shared_ptr< WThreadedRunner > > m_pendingThreads;
395 
396  /**
397  * Lock for m_pendingThreads.
398  */
399  boost::shared_mutex m_pendingThreadsLock;
400 
401  /**
402  * This method is called whenever a module inside the container crashes. By default, this method does nothing but forwarding the using
403  * WModule's signals.
404  *
405  * \param module the module that has crashed.
406  * \param exception the exception.
407  */
408  virtual void moduleError( boost::shared_ptr< WModule > module, const WException& exception );
409 
410  /**
411  * This flag denotes whether the whole container should be marked as crashed if one of the contained modules crashes. By default, this is
412  * true. The root container (the container not nested in any other container) sets this to false explicitly. Modules using the container to
413  * encapsulate a whole bunch of modules can decide, but by default they crash too.
414  */
416 
417 private:
418  // the following typedefs are for convenience; to help accessing the container in a thread safe way.
419 
420  /**
421  * A type for mapping a module to all its subscriptions
422  */
423  typedef std::pair< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscription;
424 
425  /**
426  * For shortening: a type defining a shared vector of subscriptions a module made to a notifier during add().
427  */
428  typedef std::multimap< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscriptionsType;
429 
430  /**
431  * The alias for a shared container.
432  */
434 
435  /**
436  * The const iterator type of the container.
437  */
438  typedef ModuleSubscriptionsType::const_iterator ModuleSubscriptionsConstIterator;
439 
440  /**
441  * The iterator type of the container.
442  */
443  typedef ModuleSubscriptionsType::iterator ModuleSubscriptionsIterator;
444 
445  /**
446  * The module's signal subscriptions.
447  */
448  ModuleSubscriptionsSharedType m_moduleSubscriptions;
449 };
450 
451 #endif // WMODULECONTAINER_H
452 
Base for all data loader modules.
Definition: WDataModule.h:38
WBatchLoader::SPtr loadDataSetsSynchronously(std::vector< std::string > filenames, bool suppressColormaps=false)
Loads the specified files synchronously.
WModuleContainer(std::string name="Unnamed Module Container", std::string description="Used as container for several modules.")
Constructor.
std::set< boost::shared_ptr< WThreadedRunner > > m_pendingThreads
Set of all threads that currently depend upon this container.
virtual void run()
Run thread.
std::string m_description
Description of the module.
std::list< t_GenericSignalHandlerType > m_connectorClosedNotifiers
The notifiers connected to added modules by default and fired whenever the module connectors got disc...
boost::shared_mutex m_associatedNotifiersLock
Lock for associated notifiers set.
virtual const std::string getDescription() const
Gives back a description of this module.
Class representing a single module of OpenWalnut.
Definition: WModule.h:83
boost::shared_mutex m_removedNotifiersLock
Lock for remove-notifiers set.
std::string m_name
Name of the module.
virtual const std::string getName() const
Gives back the name of this module.
virtual WModule::SPtr createAndAdd(std::string name)
Convenience method to create a module instance with a given name and automatically add it to the cont...
ModuleContainerType::iterator ModuleIterator
The iterator type of the container.
DataModuleListType getDataModules()
Returns a vector of pointers to the loaded data modules in the container.
bool m_crashIfModuleCrashes
This flag denotes whether the whole container should be marked as crashed if one of the contained mod...
virtual ~WModuleContainer()
Destructor.
std::list< t_GenericSignalHandlerType > m_connectorEstablishedNotifiers
The notifiers connected to added modules by default and fired whenever the module connectors got conn...
Base class for all classes needing to be executed in a separate thread.
std::vector< boost::shared_ptr< WModule > > ModuleVectorType
A vector of modules.
std::list< t_ModuleErrorSignalHandlerType > m_errorNotifiers
The error notifiers connected to added modules by default.
virtual void moduleMain()
Entry point after loading the module.
ModuleContainerType::const_iterator ModuleConstIterator
The const iterator type of the container.
ModuleSubscriptionsSharedType m_moduleSubscriptions
The module's signal subscriptions.
virtual void moduleError(boost::shared_ptr< WModule > module, const WException &exception)
This method is called whenever a module inside the container crashes.
virtual boost::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
virtual boost::shared_ptr< WModule > applyModule(boost::shared_ptr< WModule > applyOn, std::string what, bool tryOnly=false)
Function combines two modules.
void finishedPendingThread(boost::shared_ptr< WThreadedRunner > thread)
The specified thread has finished and does not longer depend upon this container instance.
std::list< t_ModuleGenericSignalHandlerType > m_removedNotifiers
The notifiers connected to added modules by default and fired whenever the module got removed again...
virtual void add(boost::shared_ptr< WModule > module, bool run=true)
Add a module to this container and start it.
WCombinerTypes::WCompatiblesList getPossibleConnections(boost::shared_ptr< WModule > module)
This method creates a list of combiner instances, for each possible connection that can be made betwe...
boost::shared_mutex m_connectorNotifiersLock
Lock for connector-notifiers set.
boost::shared_ptr< WBatchLoader > SPtr
Shared ptr abbreviation.
Definition: WBatchLoader.h:57
boost::shared_ptr< WModule > SPtr
Shared pointer to a WModule.
Definition: WModule.h:121
WSharedObject< ModuleSubscriptionsType > ModuleSubscriptionsSharedType
The alias for a shared container.
std::list< t_ModuleGenericSignalHandlerType > m_readyNotifiers
The ready notifiers connected to added modules by default.
boost::shared_mutex m_pendingThreadsLock
Lock for m_pendingThreads.
void addPendingThread(boost::shared_ptr< WThreadedRunner > thread)
Add the specified thread to the list of pending jobs.
std::pair< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscription
A type for mapping a module to all its subscriptions.
virtual void removeAll()
Removes all modules from this container.
std::set< boost::shared_ptr< WModule > > ModuleContainerType
For shortening: a type defining a shared vector of WModule pointers.
boost::shared_mutex m_readyNotifiersLock
Lock for ready notifiers set.
boost::shared_mutex m_errorNotifiersLock
Lock for error notifiers set.
std::set< boost::shared_ptr< WDataModule > > DataModuleListType
Simple type for WDataModule pointer lists.
WSharedObject< ModuleContainerType > ModuleSharedContainerType
The alias for a shared container.
ModuleSubscriptionsType::iterator ModuleSubscriptionsIterator
The iterator type of the container.
Class able to contain other modules.
Basic exception handler.
Definition: WException.h:38
ModuleSharedContainerType m_modules
The modules associated with this container.
WBatchLoader::SPtr loadDataSets(std::vector< std::string > filenames, bool suppressColormaps=false)
Load specified datasets.
boost::shared_ptr< WSharedObjectTicketRead< ModuleContainerType > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:64
std::list< t_ModuleGenericSignalHandlerType > m_associatedNotifiers
The notifiers connected to added modules by default and fired whenever the module got associated...
void setCrashIfModuleCrashes(bool crashIfCrashed=true)
Sets a flag denoting whether the container (which also is a module) should be marked as "crashed" if ...
ModuleSubscriptionsType::const_iterator ModuleSubscriptionsConstIterator
The const iterator type of the container.
virtual void stop()
Stops all modules inside this container.
virtual void addDefaultNotifier(MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier)
Add a specified notifier to the list of default notifiers which get connected to each added module...
ModuleSharedContainerType::ReadTicket getModules() const
Method returns a read ticket allowing read-access to the list of modules inside the container...
std::multimap< boost::shared_ptr< WModule >, boost::signals2::connection > ModuleSubscriptionsType
For shortening: a type defining a shared vector of subscriptions a module made to a notifier during a...