WModule.h 16.7 KB
Newer Older
ebaum's avatar
ebaum committed
1 2
//---------------------------------------------------------------------------
//
3
// Project: OpenWalnut ( http://www.openwalnut.org )
ebaum's avatar
ebaum committed
4
//
5 6
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
ebaum's avatar
ebaum committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

#ifndef WMODULE_H
#define WMODULE_H

Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
28
#include <vector>
ebaum's avatar
ebaum committed
29
#include <string>
30
#include <typeinfo>
ebaum's avatar
ebaum committed
31

32 33
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
34 35
#include <boost/signals2/signal.hpp>
#include <boost/function.hpp>
36
#include <boost/enable_shared_from_this.hpp>
37

38
#include "WModuleConnectorSignals.h"
39
#include "WModuleSignals.h"
40
#include "WModuleTypes.h"
41

42 43
#include "../dataHandler/WDataSet.h"
#include "../dataHandler/WDataSetSingle.h"
44
#include "../dataHandler/WValueSet.h"
45

46
#include "../common/WLogger.h"
47
#include "../common/WProperties.h"
48
#include "../common/WProgressCombiner.h"
49
#include "../common/WProgress.h"
50
#include "../common/WThreadedRunner.h"
51
#include "../common/WPrototyped.h"
52
#include "../common/WConditionSet.h"
53

54 55 56
class WModuleConnector;
class WModuleInputConnector;
class WModuleOutputConnector;
57 58
class WModuleContainer;
class WModuleFactory;
ebaum's avatar
ebaum committed
59

ebaum's avatar
ebaum committed
60 61
/**
 * Class representing a single module of OpenWalnut.
wiebel's avatar
wiebel committed
62
 * \ingroup kernel
ebaum's avatar
ebaum committed
63
 */
64
class WModule: public WThreadedRunner,
65
               public WPrototyped,
Mathias Goldau's avatar
[STYLE]  
Mathias Goldau committed
66
               public boost::enable_shared_from_this< WModule >
ebaum's avatar
ebaum committed
67
{
68
friend class WModuleConnector;  // requires access to notify members
69 70
friend class WModuleFactory;    // for proper creation of module instaces, the factory needs access to protected functions.
                                // (especially initialize)
71
friend class WModuleContainer;  // for proper management of m_container WModuleContainer needs access.
72

ebaum's avatar
ebaum committed
73 74
public:

75
    /**
76
     * Constructs a new WModule instance
ebaum's avatar
ebaum committed
77 78 79 80 81 82 83 84
     */
    WModule();

    /**
     * Destructor.
     */
    virtual ~WModule();

85 86 87 88 89 90 91 92 93 94
    /**
     * The type for the list of input connectors.
     */
    typedef std::vector< boost::shared_ptr< WModuleInputConnector > > InputConnectorList;

    /**
     * The type for the list of output connectors.
     */
    typedef std::vector< boost::shared_ptr< WModuleOutputConnector > > OutputConnectorList;

95
    /**
Mathias Goldau's avatar
[STYLE]  
Mathias Goldau committed
96
     * Gives back input connectors.
97
     *
98 99
     * \return the input connectors.
     */
100
    const InputConnectorList& getInputConnectors() const;
101

102 103 104 105 106 107 108 109
    /**
     * Finds the named connector for the module.
     *
     * \param name the name. This can be a canonical name or the connector name.
     *
     * \return the connector.
     * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
     */
ledig's avatar
ledig committed
110
    boost::shared_ptr< WModuleInputConnector > getInputConnector( std::string name );
111

112
    /**
Mathias Goldau's avatar
[STYLE]  
Mathias Goldau committed
113
     * Gives back output connectors.
114
     *
115 116
     * \return the output connectors.
     */
117
    const OutputConnectorList& getOutputConnectors() const;
118

119 120 121 122 123 124 125 126
    /**
     * Finds the named connector for the module.
     *
     * \param name the name. This can be a canonical name or the connector name.
     *
     * \return the connector.
     * \throw WModuleConnectorNotFound thrown whenever the module does not provide the specified connector.
     */
ledig's avatar
ledig committed
127
    boost::shared_ptr< WModuleOutputConnector > getOutputConnector( std::string name );
128

129 130 131 132 133
    /**
     * Return a pointer to the properties object of the module.
     *
     * \return the properties.
     */
134
    boost::shared_ptr< WProperties > getProperties() const;
135

136 137 138 139 140 141 142
    /**
     * Return a pointer to the information properties object of the module. The module intends these properties to not be modified.
     *
     * \return the properties.
     */
    boost::shared_ptr< WProperties > getInformationProperties() const;

143
    /**
144
     * Determines whether the module instance is properly initialized.
145
     *
146 147
     * \return true if properly initialized.
     */
148
    const WBoolFlag& isInitialized() const;
149 150 151

    /**
     * Checks whether the module instance is ready to be used. This is the case if isInitialized && isAssociated.
152
     *
153 154
     * \return isInitialized && isAssociated
     */
155
    const WBoolFlag&  isUseable() const;
156

157 158
     /**
      * Checks whether this module is associated with an container.
159
      *
160 161
      * \return true if associated.
      */
162
    const WBoolFlag&  isAssociated() const;
163

164 165 166 167 168 169 170
     /**
      * Checks whether this module is ready.
      *
      * \return true if ready.
      */
    const WBoolFlag&  isReady() const;

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    /**
     * Checks whether this module has been crashed. This will be true whenever the module throws an unhandled exception.
     *
     * \return true if there has been an exception during moduleMain().
     */
    const WBoolFlag& isCrashed() const;

    /**
     * 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
     * crashed before ready() got called, you most probably would wait endlessly.
     *
     * \return isReady || isCrashed.
     */
    const WBoolFlag& isReadyOrCrashed() const;

186 187 188 189 190 191 192
    /**
     * Returns a flag denoting whether the thread currently is running or nor. It is also useful to get a callback whenever a module stops.
     *
     * \return the flag
     */
    const WBoolFlag& isRunning() const;

193 194
     /**
      * The container this module is associated with.
195
      *
196 197
      * \return the container.
      */
198
    boost::shared_ptr< WModuleContainer > getAssociatedContainer() const;
199 200 201 202

    /**
     * Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it
     * should never be initialized or modified in some other way. A simple new instance is required.
203
     *
204 205 206 207
     * \return the prototype used to create every module in OpenWalnut.
     */
    virtual boost::shared_ptr< WModule > factory() const = 0;

208
    /**
209
     * Connects a specified notify function with a signal this module instance is offering.
210
     *
211 212 213 214 215 216
     * \exception WModuleSignalSubscriptionFailed thrown if the signal can't be connected.
     *
     * \param signal the signal to connect to.
     * \param notifier the notifier function to bind.
     *
     * \return connection descriptor.
217
     */
218
    virtual boost::signals2::connection subscribeSignal( MODULE_SIGNAL signal, t_ModuleGenericSignalHandlerType notifier );
219 220 221 222 223 224 225 226 227 228 229

    /**
     * Connects a specified notify function with a signal this module instance is offering.
     *
     * \exception WModuleSignalSubscriptionFailed thrown if the signal can't be connected.
     *
     * \param signal the signal to connect to.
     * \param notifier the notifier function to bind.
     *
     * \return connection descriptor.
     */
230
    virtual boost::signals2::connection subscribeSignal( MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier );
231

232 233 234 235 236 237 238
    /**
     * Gets the modules base progress. This is actually a progress combiner, which bundles all progresses.
     *
     * \return the progress combiner for this module.
     */
    virtual boost::shared_ptr< WProgressCombiner > getRootProgressCombiner();

239 240 241 242 243
    /**
     * Get the icon for this module in XPM format.
     */
    virtual const char** getXPMIcon() const;

244 245 246 247 248 249 250 251
    /**
     * Gets the type of the module. This is useful for FAST differentiation between several modules like standard modules and data
     * modules which play a special role in OpenWalnut/Kernel.
     *
     * \return the Type. If you do not overwrite this method, it will return MODULE_ARBITRARY.
     */
    virtual MODULE_TYPE getType() const;

252 253 254 255 256 257
    /**
     * Completely disconnects all connected connectors of this module. This is useful to isolate a module (for deletion, removal from a container
     * and so on.)
     */
    void disconnect();

258 259 260 261 262
protected:

    /**
     * Entry point after loading the module. Runs in separate thread.
     */
263 264 265 266 267 268
    virtual void moduleMain() = 0;

    /**
     * Thread entry point. Calls moduleMain and sends error notification if needed.
     */
    void threadMain();
ebaum's avatar
ebaum committed
269

270 271
     /**
      * Sets the container this module is associated with.
272
      *
273 274 275 276
      * \param container the container to associate with.
      */
    void setAssociatedContainer( boost::shared_ptr< WModuleContainer > container );

277 278 279 280 281
    // **************************************************************************************************************************
    //
    // Connector Management
    //
    // **************************************************************************************************************************
282

283
    /**
284 285
     * Initialize connectors in this function. This function must not be called multiple times for one module instance.
     * The module container manages calling those functions -> so just implement it.
286
     */
287 288
    virtual void connectors();

289 290 291 292 293 294 295 296
    /**
     * Initialize properties in this function. This function must not be called multiple times for one module instance.
     * The module container manages calling those functions -> so just implement it. Once initialized the number and type
     * of all properties should be set.
     */
    virtual void properties();

    /**
297 298 299 300
     * Manages connector initialization. Gets called by module container.
     *
     * \throw WModuleConnectorInitFailed if called multiple times.
     */
301 302
    void initialize();

303
    /**
304
     * Called whenever the module should shutdown.
305
     */
306
    virtual void cleanup();
307

308
    /**
309
     * Adds the specified connector to the list of inputs.
310
     *
311 312
     * \param con the connector.
     */
313
    void addConnector( boost::shared_ptr<WModuleInputConnector> con );
ebaum's avatar
ebaum committed
314

315
    /**
316
     * Adds the specified connector to the list of outputs.
317
     *
318
     * \param con the connector.
ebaum's avatar
ebaum committed
319
     */
320
    void addConnector( boost::shared_ptr<WModuleOutputConnector> con );
ebaum's avatar
ebaum committed
321

322
    /**
323 324 325
     * Removes all connectors properly. It disconnects the connectors and cleans the connectors list.
     */
    void removeConnectors();
326

327 328 329 330 331
    /**
     * Callback for m_active. Overwrite this in your modules to handle m_active changes separately.
     */
    virtual void activate();

332 333 334 335 336 337
    // **************************************************************************************************************************
    //
    // Signal handlers that HAVE to be in every module. By default they do nothing. You should overwrite them to get notified
    // with the corresponding signal
    //
    // **************************************************************************************************************************
338

339
    /**
340 341 342
     * Gives the signal handler function responsible for a given signal. Modules defining own signal handlers should overwrite
     * this function. This function is protected since boost::functions are callable, which is what is not wanted here. Just
     * signals should call them.
343
     *
344
     * \param signal the signal to get the handler for.
345
     *
346 347 348 349
     * \return the signal handler for "signal".
     */
    virtual const t_GenericSignalHandlerType getSignalHandler( MODULE_CONNECTOR_SIGNAL signal );

350
    /**
351
     * Gets called whenever a connector gets connected to the specified input.
352
     *
353
     * \param here the connector of THIS module that got connected to "there"
354
     * \param there the connector that has been connected with the connector "here" of this module.
355 356 357
     */
    virtual void notifyConnectionEstablished( boost::shared_ptr<WModuleConnector> here,
                                              boost::shared_ptr<WModuleConnector> there );
358
    /**
359
     * Gets called whenever a connection between a remote and local connector gets closed.
360
     *
361 362 363 364 365
     * \param here the connector of THIS module getting disconnected.
     * \param there the connector of the other module getting disconnected.
     */
    virtual void notifyConnectionClosed( boost::shared_ptr<WModuleConnector> here, boost::shared_ptr<WModuleConnector> there );

366
    /**
367
     * Gets called when the data on one input connector changed.
368
     *
369 370
     * \param input the input connector receiving the change.
     * \param output the output connector sending the change notification.
371
     */
372 373
    virtual void notifyDataChange( boost::shared_ptr<WModuleConnector> input,
                                   boost::shared_ptr<WModuleConnector> output );
374

Mathias Goldau's avatar
[STYLE]  
Mathias Goldau committed
375 376 377 378 379
    /**
     * Call this whenever your module is ready and can react on property changes.
     */
    void ready();

380 381 382 383 384
    /**
     * Logger instance for comfortable info logging. Simply use logInfo() << "my info".
     *
     * \return the logger stream.
     */
385
    wlog::WStreamedLogger infoLog() const;
386

387 388 389 390 391
    /**
     * Logger instance for comfortable debug logging. Simply use logDebug() << "my debug".
     *
     * \return the logger stream.
     */
392
    wlog::WStreamedLogger debugLog() const;
393

394 395 396 397 398
    /**
     * Logger instance for comfortable warning- logs. Simply use logWarning() << "my warning".
     *
     * \return the logger stream.
     */
399
    wlog::WStreamedLogger warnLog() const;
400

401 402 403 404 405
    /**
     * Logger instance for comfortable error logging. Simply use logError() << "my error".
     *
     * \return the logger stream.
     */
406
    wlog::WStreamedLogger errorLog() const;
407

408 409 410 411 412 413
    // **************************************************************************************************************************
    //
    // Members
    //
    // **************************************************************************************************************************

414 415 416
    /**
     * The property object for the module.
     */
417
    boost::shared_ptr< WProperties > m_properties;
418

419 420 421 422 423 424 425
    /**
     * The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION". It is useful to define some property
     * 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
     * m_properties.
     */
    boost::shared_ptr< WProperties > m_infoProperties;

426 427 428 429 430
    /**
     * Progress indicator used as parent for all progress' of this module.
     */
    boost::shared_ptr< WProgressCombiner > m_progress;

431
    /**
432 433
     * True if everything is initialized and ready to be used.
     */
434 435
    WBoolFlag m_initialized;

436
    /**
437 438 439 440
     * True if container got associated with this flag.
     */
    WBoolFlag m_isAssociated;

441
    /**
442 443 444
     * True if associated && initialized.
     */
    WBoolFlag m_isUsable;
445

446 447 448 449 450
    /**
     * True if ready() was called.
     */
    WBoolFlag m_isReady;

451 452 453 454 455 456 457 458 459 460
    /**
     * True whenever an exception is thrown during moduleMain.
     */
    WBoolFlag m_isCrashed;

    /**
     * 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.
     */
    WBoolFlag m_isReadyOrCrashed;

461 462 463 464 465
    /**
     * True if the module currently is running.
     */
    WBoolFlag m_isRunning;

466 467 468 469 470
    /**
     * Progress indicator for the "ready" state.
     */
    boost::shared_ptr< WProgress > m_readyProgress;

471 472 473 474 475
    /**
     * The internal state of the module. This is, by default, simply the exit flag from WThreadedRunner.
     */
    WConditionSet m_moduleState;

476 477 478 479 480 481 482 483
    /**
     * The container this module belongs to.
     */
    boost::shared_ptr< WModuleContainer > m_container;

    /**
     * Set of input connectors associated with this module.
     */
484
    InputConnectorList m_inputConnectors;
485 486 487 488

    /**
     * Set of output connectors associated with this module.
     */
489
    OutputConnectorList m_outputConnectors;
490

491 492 493 494 495
    /**
     * True whenever the module should be active
     */
    WPropBool m_active;

496 497 498 499 500
    /**
     * This property holds a user specified name for the current module instance.
     */
    WPropString m_runtimeName;

501 502 503
private:

     /**
Alexander Wiebel's avatar
Alexander Wiebel committed
504
     * Lock for m_inputConnectors.
505
     */
Alexander Wiebel's avatar
Alexander Wiebel committed
506
    // boost::shared_mutex m_inputConnectorsLock;
507

508
    /**
Alexander Wiebel's avatar
Alexander Wiebel committed
509
     * Lock for m_outputConnectors.
510
     */
Alexander Wiebel's avatar
Alexander Wiebel committed
511
    // boost::shared_mutex m_outputConnectorsLock;
512 513 514 515

    /**
     * Signal fired whenever a module main thread is ready.
     */
516 517 518 519 520 521
    t_ModuleGenericSignalType signal_ready;

    /**
     * Signal fired whenever a module main thread throws an exception/error.
     */
    t_ModuleErrorSignalType signal_error;
ebaum's avatar
ebaum committed
522 523
};

524 525 526 527 528 529 530
/**
 * \defgroup modules Modules
 *
 * \brief
 * This group contains modules of OpenWalnut.
 * The term modules can be understood as "plugin" or "algorithm" in this context.
 */
ebaum's avatar
ebaum committed
531 532
#endif  // WMODULE_H