Commit c9d29bf8 authored by Mathias Goldau's avatar Mathias Goldau
Browse files

[MERGE]

parents 439b44cb 68502844
......@@ -31,8 +31,10 @@
#include "WModuleInputConnector.h"
#include "WModuleOutputConnector.h"
#include "WModuleConnectorSignals.h"
#include "WModuleContainer.h"
#include "exceptions/WModuleSignalUnknown.h"
#include "exceptions/WModuleConnectorInitFailed.h"
#include "exceptions/WModuleUninitialized.h"
#include "WModule.h"
......@@ -42,6 +44,7 @@ WModule::WModule():
{
// initialize members
m_properties = boost::shared_ptr< WProperties >( new WProperties() );
m_container = boost::shared_ptr< WModuleContainer >();
}
WModule::~WModule()
......@@ -60,9 +63,9 @@ void WModule::addConnector( boost::shared_ptr< WModuleOutputConnector > con )
m_outputConnectors.insert( con );
}
void WModule::removeConnectors()
void WModule::disconnectAll()
{
m_initialized = false;
// TODO(ebaum): flat or deep removal? What to do with connected modules?
// remove connections and their signals
for( std::set<boost::shared_ptr< WModuleInputConnector > >::iterator listIter = m_inputConnectors.begin();
......@@ -75,6 +78,14 @@ void WModule::removeConnectors()
{
( *listIter )->disconnectAll();
}
}
void WModule::removeConnectors()
{
m_initialized = false;
// remove connections and their signals
disconnectAll();
// clean up list
// this should delete the connector since nobody else *should* have another shared_ptr to them
......@@ -90,7 +101,6 @@ void WModule::properties()
{
}
void WModule::initialize()
{
// doing it twice is not allowed
......@@ -104,6 +114,8 @@ void WModule::initialize()
}
connectors();
// TODO(ebaum): should properties be initialized here?
// properties();
m_initialized = true;
}
......@@ -114,6 +126,16 @@ void WModule::cleanup()
removeConnectors();
}
boost::shared_ptr< WModuleContainer > WModule::getAssociatedContainer() const
{
return m_container;
}
void WModule::setAssociatedContainer( boost::shared_ptr< WModuleContainer > container )
{
m_container = container;
}
const std::set<boost::shared_ptr< WModuleInputConnector > >& WModule::getInputConnectors() const
{
return m_inputConnectors;
......@@ -147,6 +169,17 @@ bool WModule::isInitialized() const
return m_initialized;
}
bool WModule::isAssociated() const
{
// true if the pointer is set
return ( m_container == boost::shared_ptr< WModuleContainer >() );
}
bool WModule::isUseable() const
{
return isInitialized() && isAssociated();
}
void WModule::notifyConnectionEstablished( boost::shared_ptr< WModuleConnector > /*here*/,
boost::shared_ptr< WModuleConnector > /*there*/ )
{
......@@ -165,7 +198,7 @@ void WModule::notifyDataChange( boost::shared_ptr< WModuleConnector > /*input*/,
// By default this callback does nothing. Overwrite it in your module.
}
boost::shared_ptr< WProperties > WModule::getProperties()
boost::shared_ptr< WProperties > WModule::getProperties() const
{
return m_properties;
}
......
......@@ -43,6 +43,8 @@
class WModuleConnector;
class WModuleInputConnector;
class WModuleOutputConnector;
class WModuleContainer;
class WModuleFactory;
/**
* Class representing a single module of OpenWalnut.
......@@ -52,6 +54,9 @@ class WModule: public WThreadedRunner,
public boost::enable_shared_from_this<WModule>
{
friend class WModuleConnector; // requires access to notify members
friend class WModuleFactory; // for proper creation of module instaces, the factory needs access to protected functions.
// (especially initialize)
friend class WModuleContainer; // for proper management of m_container WModuleContainer needs access.
public:
......@@ -94,14 +99,43 @@ public:
/**
* Return a pointer to the properties object of the module
*/
boost::shared_ptr<WProperties> getProperties();
boost::shared_ptr<WProperties> getProperties() const;
/**
* Determines whether the module instance is properly initialized.
*
* \return true if properly initialized.
*/
bool isInitialized() const;
bool isInitialized() const;
/**
* Checks whether the module instance is ready to be used. This is the case if isInitialized && isAssociated.
*
* \return isInitialized && isAssociated
*/
bool isUseable() const;
/**
* Checks whether this module is associated with an container.
*
* \return true if associated.
*/
bool isAssociated() const;
/**
* The container this module is associated with.
*
* \return the container.
*/
boost::shared_ptr< WModuleContainer > getAssociatedContainer() const;
/**
* 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.
*
* \return the prototype used to create every module in OpenWalnut.
*/
virtual boost::shared_ptr< WModule > factory() const = 0;
/**
* Takes all the relevant GUI signals and connects them to own member functions.
......@@ -116,6 +150,13 @@ protected:
*/
virtual void threadMain() = 0;
/**
* Sets the container this module is associated with.
*
* \param container the container to associate with.
*/
void setAssociatedContainer( boost::shared_ptr< WModuleContainer > container );
// **************************************************************************************************************************
//
// Connector Management
......@@ -135,7 +176,6 @@ protected:
*/
virtual void properties();
/**
* Manages connector initialization. Gets called by module container.
*
......@@ -148,17 +188,6 @@ protected:
*/
void cleanup();
/**
* Set of input connectors associated with this module.
* NOTE: we need a thread safe list implementation!
*/
std::set<boost::shared_ptr<WModuleInputConnector> > m_inputConnectors;
/**
* Set of output connectors associated with this module.
*/
std::set<boost::shared_ptr<WModuleOutputConnector> > m_outputConnectors;
/**
* Adds the specified connector to the list of inputs.
*
......@@ -178,6 +207,11 @@ protected:
*/
void removeConnectors();
/**
* Completely disconnects all connected connectors of this module.
*/
void disconnectAll();
// **************************************************************************************************************************
//
// Signal handlers that HAVE to be in every module. By default they do nothing. You should overwrite them to get notified
......@@ -221,16 +255,37 @@ protected:
virtual void notifyDataChange( boost::shared_ptr<WModuleConnector> input,
boost::shared_ptr<WModuleConnector> output );
/**
// **************************************************************************************************************************
//
// Members
//
// **************************************************************************************************************************
/**
* the property object for the module
*/
boost::shared_ptr<WProperties> m_properties;
boost::shared_ptr< WProperties > m_properties;
/**
* True if everything is initialized and ready to be used.
*/
bool m_initialized;
/**
* The container this module belongs to.
*/
boost::shared_ptr< WModuleContainer > m_container;
/**
* Set of input connectors associated with this module.
* NOTE: we need a thread safe list implementation!
*/
std::set<boost::shared_ptr<WModuleInputConnector> > m_inputConnectors;
/**
* Set of output connectors associated with this module.
*/
std::set<boost::shared_ptr<WModuleOutputConnector> > m_outputConnectors;
private:
/**
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// 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/>.
//
//---------------------------------------------------------------------------
#include <string>
#include <sstream>
#include "WModule.h"
#include "exceptions/WModuleUninitialized.h"
#include "../common/WLogger.h"
#include "WModuleContainer.h"
WModuleContainer::WModuleContainer(): boost::enable_shared_from_this< WModuleContainer >()
{
// initialize members
}
WModuleContainer::~WModuleContainer()
{
// cleanup
}
void WModuleContainer::add( boost::shared_ptr< WModule > module )
{
if ( !module->isInitialized() )
{
std::ostringstream s;
s << "Could not add module " << module->getName() << " to container. Reason: module not initialized.";
throw WModuleUninitialized( s.str() );
}
// already associated with this container?
if ( module->getAssociatedContainer() == shared_from_this() )
{
return;
}
// is this module already associated?
if ( module->isAssociated() )
{
module->getAssociatedContainer()->remove( module );
}
// get write lock
boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_moduleSetLock );
m_modules.insert( module );
lock.unlock();
module->setAssociatedContainer( shared_from_this() );
// now module->isUsable() is true
// -> so run it
module->run();
}
void WModuleContainer::remove( boost::shared_ptr< WModule > module )
{
if ( module->getAssociatedContainer() != shared_from_this() )
{
return;
}
// stop module
WLogger::getLogger()->addLogMessage( "Waiting for module " + module->getName() + " to finish." , "ModuleContainer", LL_DEBUG );
module->wait( true );
// get write lock
boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_moduleSetLock );
m_modules.erase( module );
lock.unlock();
module->setAssociatedContainer( boost::shared_ptr< WModuleContainer >() );
// TODO(ebaum): flat or deep removal? What to do with associated modules?
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// 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 WMODULECONTAINER_H
#define WMODULECONTAINER_H
#include <set>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
class WModule;
/**
* Class able to contain other modules. It manages several tasks like finding appropriate modules, managing data modules and
* module initialization.
*
* \ingroup Kernel
*/
class WModuleContainer: public boost::enable_shared_from_this< WModuleContainer >
{
public:
/**
* Default constructor.
*/
WModuleContainer();
/**
* Destructor.
*/
virtual ~WModuleContainer();
/**
* Add a module to this container and start it. Please note, that a module can be added only once. If it already is
* associated with this container nothing happens.
*
* \param module the module to add.
* \throw WModuleUninitialized thrown whenever someone wants to add a module not yet initialized.
*/
virtual void add( boost::shared_ptr< WModule > module );
/**
* Remove the given module from this container if it is associated with it. TODO(ebaum): deep removal? flat removal?
*
* \param module the module to remove.
*/
virtual void remove( boost::shared_ptr< WModule > module );
protected:
/**
* Lock for module set.
*/
boost::shared_mutex m_moduleSetLock;
/**
* The modules associated with this container.
*/
std::set< boost::shared_ptr< WModule > > m_modules;
private:
};
#endif // WMODULECONTAINER_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// 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/>.
//
//---------------------------------------------------------------------------
#include <set>
#include "../common/WLogger.h"
#include "../modules/data/WMData.hpp"
#include "../modules/navSlices/WMNavSlices.h"
#include "../modules/coordinateSystem/WMCoordinateSystem.h"
#include "../modules/fiberDisplay/WMFiberDisplay.h"
#include "../modules/fiberCulling/WMFiberCulling.h"
#include "../modules/fiberClustering/WMFiberClustering.h"
#include "../modules/marchingCubes/WMMarchingCubes.h"
#include "../modules/eegTest/WMEEGTest.h"
#include "exceptions/WPrototypeUnknown.h"
#include "WModuleFactory.h"
// factory instance as singleton
boost::shared_ptr< WModuleFactory > WModuleFactory::m_instance = boost::shared_ptr< WModuleFactory >();
WModuleFactory::WModuleFactory()
{
// initialize members
}
WModuleFactory::~WModuleFactory()
{
// cleanup
}
void WModuleFactory::load()
{
// load modules
WLogger::getLogger()->addLogMessage( "Loading Modules", "ModuleFactory", LL_INFO );
// operation must be exclusive
boost::unique_lock< boost::shared_mutex > lock = boost::unique_lock< boost::shared_mutex >( m_prototypesLock );
// currently the prototypes are added by hand. This will be done automatically later.
m_prototypes.insert( boost::shared_ptr< WModule >( new WMNavSlices() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMFiberDisplay() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMFiberCulling() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMFiberClustering() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMCoordinateSystem() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMEEGTest() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMMarchingCubes() ) );
lock.unlock();
// for this a read lock is sufficient
boost::shared_lock< boost::shared_mutex > slock = boost::shared_lock< boost::shared_mutex >( m_prototypesLock );
// initialize every module in the set
for( std::set< boost::shared_ptr< WModule > >::iterator list_iter = m_prototypes.begin(); list_iter != m_prototypes.end();
++list_iter )
{
WLogger::getLogger()->addLogMessage( "Loading module: " + ( *list_iter )->getName(), "ModuleFactory", LL_DEBUG );
( *list_iter )->initialize();
}
slock.unlock();
}
boost::shared_ptr< WModule > WModuleFactory::create( boost::shared_ptr< WModule > prototype )
{
// for this a read lock is sufficient
boost::shared_lock< boost::shared_mutex > slock = boost::shared_lock< boost::shared_mutex >( m_prototypesLock );
// ensure this one is a prototype and nothing else
if ( m_prototypes.count( prototype ) == 0 )
{
throw WPrototypeUnknown( "Could not clone module " + prototype->getName() + " since it is no prototype." );
}
slock.unlock();
// call prototypes factory function
boost::shared_ptr< WModule > clone = boost::shared_ptr< WModule >( prototype->factory() );
clone->initialize();
return clone;
}
boost::shared_ptr< WModuleFactory > WModuleFactory::getModuleFactory()
{
if ( !m_instance )
{
m_instance = boost::shared_ptr< WModuleFactory >( new WModuleFactory() );
}
return m_instance;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// 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 WMODULEFACTORY_H
#define WMODULEFACTORY_H
#include <set>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include "WModule.h"
/**
* Class able to create a new copy of an arbitrary module. It uses the Factory and Prototype design pattern.
*/
class WModuleFactory
{
public:
/**
* Default constructor.
*/
WModuleFactory();
/**
* Destructor.
*/
virtual ~WModuleFactory();
/**
* Loads the modules and creates prototypes.
*/
void load();
/**
* Create a new and initialized module using the specified prototype.
*
* \param prototype the prototype to clone.
*
* \return the module created using the prototype.
*/
boost::shared_ptr< WModule > create( boost::shared_ptr< WModule > prototype );
/**
* Returns instance of the module factory to use to create modules.
*
* \return the running module factory.