Commit fd745683 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum

[ADD] - basic module factory functions

parent a25b673f
......@@ -31,6 +31,7 @@
#include "WModuleInputConnector.h"
#include "WModuleOutputConnector.h"
#include "WModuleConnectorSignals.h"
#include "WModuleContainer.h"
#include "exceptions/WModuleSignalUnknown.h"
#include "exceptions/WModuleConnectorInitFailed.h"
......@@ -42,6 +43,7 @@ WModule::WModule():
{
// initialize members
m_properties = boost::shared_ptr< WProperties >( new WProperties() );
m_container = boost::shared_ptr< WModuleContainer >();
}
WModule::~WModule()
......@@ -60,9 +62,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 +77,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 +100,6 @@ void WModule::properties()
{
}
void WModule::initialize()
{
// doing it twice is not allowed
......@@ -104,6 +113,8 @@ void WModule::initialize()
}
connectors();
// TODO(ebaum): should properties be initialized here?
// properties();
m_initialized = true;
}
......@@ -114,6 +125,11 @@ void WModule::cleanup()
removeConnectors();
}
boost::shared_ptr< WModuleContainer > WModule::getAssociatedContainer() const
{
return m_container;
}
const std::set<boost::shared_ptr< WModuleInputConnector > >& WModule::getInputConnectors() const
{
return m_inputConnectors;
......@@ -147,6 +163,12 @@ bool WModule::isInitialized() const
return m_initialized;
}
bool WModule::isAssociated() const
{
// true if the pointer is set
return m_container;
}
void WModule::notifyConnectionEstablished( boost::shared_ptr< WModuleConnector > /*here*/,
boost::shared_ptr< WModuleConnector > /*there*/ )
{
......@@ -165,7 +187,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,8 @@ 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)
public:
......@@ -94,7 +98,7 @@ 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.
......@@ -103,6 +107,28 @@ public:
*/
bool isInitialized() 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.
* NOTE: this is only temporal. See ticket 142.
......@@ -135,7 +161,6 @@ protected:
*/
virtual void properties();
/**
* Manages connector initialization. Gets called by module container.
*
......@@ -148,17 +173,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 +192,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 +240,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:
/**
......
......@@ -22,9 +22,15 @@
//
//---------------------------------------------------------------------------
#include <string>
#include <sstream>
#include "WModule.h"
#include "exceptions/WModuleUninitialized.h"
#include "WModuleContainer.h"
WModuleContainer::WModuleContainer()
WModuleContainer::WModuleContainer(): boost::enable_shared_from_this< WModuleContainer >()
{
// initialize members
}
......@@ -34,3 +40,46 @@ 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();
}
void WModuleContainer::remove( boost::shared_ptr< WModule > module )
{
if ( module->getAssociatedContainer() != shared_from_this() )
{
return;
}
// get write lock
boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_moduleSetLock );
m_modules.erase( module );
lock.unlock();
// TODO(ebaum): flat or deep removal? What to do with associated modules?
}
......@@ -25,13 +25,21 @@
#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
class WModuleContainer: public boost::enable_shared_from_this< WModuleContainer >
{
public:
......@@ -45,8 +53,34 @@ public:
*/
virtual ~WModuleContainer();
/**
* Add a module to this container. 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:
};
......
//---------------------------------------------------------------------------
//
// 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 "WModuleFactory.h"
// factory instance as singleton
boost::shared_ptr< WModuleFactory > WModuleFactory::m_instance = boost::shared_ptr< WModuleFactory >();
WModuleFactory::WModuleFactory()
{
// initialize members
}
WModuleFactory::~WModuleFactory()
{
// cleanup
}
boost::shared_ptr< WModule > WModuleFactory::create( boost::shared_ptr< WModule > prototype )
{
// 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 <boost/shared_ptr.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();
/**
* 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.
*/
static boost::shared_ptr< WModuleFactory > getModuleFactory();
protected:
private:
/**
* Singleton instance of WModuleFactory.
*/
static boost::shared_ptr< WModuleFactory > m_instance;
};
#endif // WMODULEFACTORY_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 <string>
#include "WModuleUninitialized.h"
WModuleUninitialized::WModuleUninitialized( const std::string& msg ): WKernelException( msg )
{
// initialize members
}
WModuleUninitialized::~WModuleUninitialized() throw()
{
// cleanup
}
//---------------------------------------------------------------------------
//
// 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 WMODULEUNINITIALIZED_H
#define WMODULEUNINITIALIZED_H
#include <string>
#include "WKernelException.h"
/**
* General purpose exception and therefore base class for all kernel related exceptions.
* \ingroup kernel
*/
class WModuleUninitialized: public WKernelException
{
public:
/**
* Default constructor.
* \param msg the exception message.
*/
explicit WModuleUninitialized( const std::string& msg = "Module Uninitialized" );
/**
* Destructor.
*/
virtual ~WModuleUninitialized() throw();
protected:
private:
};
#endif // WMODULEUNINITIALIZED_H
......@@ -53,7 +53,7 @@ class WModuleImpl: public WModule
friend class WModuleConnectorTest;
public:
explicit WModuleImpl( std::string n ): WModule()
explicit WModuleImpl( std::string n="?" ): WModule()
{
this->n = n;
}
......@@ -62,6 +62,11 @@ public:
{
}
virtual boost::shared_ptr< WModule > factory() const
{
return boost::shared_ptr< WModule >( new WModuleImpl() );
}
// required since pure virtual
virtual const std::string getName() const
{
......
......@@ -41,6 +41,11 @@ WMCoordinateSystem::~WMCoordinateSystem()
{
}
boost::shared_ptr< WModule > WMCoordinateSystem::factory() const
{
return boost::shared_ptr< WModule >( new WMCoordinateSystem() );
}
void WMCoordinateSystem::threadMain()
{
createGeometry();
......
......@@ -76,6 +76,14 @@ public:
*/
void connectToGui();
/**
* 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;
protected:
/**
* \par Description
......
......@@ -50,7 +50,7 @@ public:
* \par Description
* Default constructor.
*/
// WMData();
WMData();
/**
* \par Description
......@@ -93,6 +93,14 @@ public:
*/
virtual osg::ref_ptr<osg::Texture3D> getTexture3D();
/**
* 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;
protected:
/**
* \par Description
......@@ -148,16 +156,16 @@ private:
};
// TODO(schurade, ebaum): do we still need/want that constructor?
// template < typename T >
// WMData<T>::WMData():
// WModule()
// {
// // WARNING: initializing connectors inside the constructor will lead to an exception.
// // Implement WModule::initializeConnectors instead.
//