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