Commit 3f4c8829 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[CHANGE] - completed data transfer mechanism and its test

parent f2099dd2
......@@ -46,6 +46,13 @@ MODULE_CONNECTOR_SIGNAL;
// Types
// **************************************************************************************************************************
/**
* Signal transmitting sender and receiver.
*
* \param boost::shared_ptr<WModuleConnector> this should be the receiver, depending on specific signal.
* \param boost::shared_ptr<WModuleConnector> this should be the sender, depending on specific signal.
*
*/
typedef boost::function<void ( boost::shared_ptr<WModuleConnector>,
boost::shared_ptr<WModuleConnector> )> t_GenericSignalHandlerType;
......@@ -58,6 +65,5 @@ typedef boost::function<void ( boost::shared_ptr<WModuleConnector>,
typedef boost::signals2::signal<void ( boost::shared_ptr<WModuleConnector>,
boost::shared_ptr<WModuleConnector> )> t_GenericSignalType;
#endif // WMODULECONNECTORSIGNALS_H
......@@ -34,6 +34,10 @@ WModuleInputConnector::WModuleInputConnector( boost::shared_ptr<WModule> module,
WModuleConnector( module, name, description )
{
// initialize members
// connect some signals
// This signal is some kind of "forwarder" for the data_changed signal of an output connector.
signal_DataChanged.connect( getSignalHandler( DATA_CHANGED ) );
}
WModuleInputConnector::~WModuleInputConnector()
......@@ -56,9 +60,12 @@ void WModuleInputConnector::connectSignals( boost::shared_ptr<WModuleConnector>
{
WModuleConnector::connectSignals( con );
// connect dataChange signal
// connect dataChange signal with an internal handler to ensure we can add the "input" connector pointer, since the output
// connector does not set this information.
// NOTE: con will be an WModuleOutputConnector
m_DataChangedConnection = con->subscribeSignal( DATA_CHANGED, getSignalHandler( DATA_CHANGED ) );
m_DataChangedConnection = con->subscribeSignal( DATA_CHANGED,
boost::bind( &WModuleInputConnector::notifyDataChange, this, _1, _2 )
);
}
void WModuleInputConnector::disconnectSignals( boost::shared_ptr<WModuleConnector> con )
......@@ -68,3 +75,11 @@ void WModuleInputConnector::disconnectSignals( boost::shared_ptr<WModuleConnecto
WModuleConnector::disconnectSignals( con );
}
void WModuleInputConnector::notifyDataChange( boost::shared_ptr<WModuleConnector> /*input*/,
boost::shared_ptr<WModuleConnector> output )
{
// since the output connector is not able to fill the parameter "input" we need to forward this message and fill it with the
// proper information
signal_DataChanged( shared_from_this(), output );
}
......@@ -29,6 +29,7 @@
#include "WModule.h"
#include "WModuleConnector.h"
#include "WModuleConnectorSignals.h"
/**
* Class implementing input connection functionality between modules.
......@@ -77,10 +78,26 @@ protected:
*/
virtual void disconnectSignals( boost::shared_ptr<WModuleConnector> con );
/**
* Gets called when the data on this input connector changed.
*
* \param input the input connector receiving the change.
* \param output the output connector sending the change notification.
*/
virtual void notifyDataChange( boost::shared_ptr<WModuleConnector> input,
boost::shared_ptr<WModuleConnector> output );
private:
/**
* Connection for Data Changed signal.
* Signal for "DATA_CHANGED" Events. We use a separate signal here (instead of using the signal send by the connected output)
* since the output can not determine the receiver when signalling. So we use an own signal handler and signal to "forward"
* the message and complete the information with a this-pointer.
*/
t_GenericSignalType signal_DataChanged;
/**
* Connection for Data Changed signal of the connected output connector.
*/
boost::signals2::connection m_DataChangedConnection;
};
......
......@@ -26,10 +26,15 @@
#define WMODULEINPUTDATA_H
#include <string>
#include <sstream>
// this seems to be necessary
#include <boost/shared_ptr.hpp>
#include <boost/thread/locks.hpp>
// this is necessary since we have some kind of cyclic includes
template < typename T > class WModuleInputData;
#include "WModuleOutputData.hpp"
#include "exceptions/WModuleConnectorUnconnected.h"
#include "WModuleInputConnector.h"
......@@ -64,11 +69,34 @@ public:
/**
* Gives the currently set data.
*
* \throw WModuleConnectorUnconnected if someone is requesting data but this connector is not connected.
*
* \return the data currently set.
*/
const boost::shared_ptr<T> getData() const
const boost::shared_ptr<T> getData()
{
//return m_data;
// get a lock
boost::shared_lock<boost::shared_mutex> lock = boost::shared_lock<boost::shared_mutex>( m_ConnectionListLock );
// is there something in the list?
if ( m_Connected.begin()==m_Connected.end() )
{
lock.unlock();
// throw an exception
std::ostringstream s;
s << "Unable to acquire data from unconnected input \"" << getCanonicalName() << "\".";
throw WModuleConnectorUnconnected( s.str() );
}
// get data
boost::shared_ptr<T> dat = boost::shared_dynamic_cast<WModuleOutputData<T> >( *m_Connected.begin() )->getData();
// unlock and return
lock.unlock();
return dat;
};
protected:
......
......@@ -71,5 +71,6 @@ boost::signals2::connection WModuleOutputConnector::subscribeSignal( MODULE_CONN
void WModuleOutputConnector::propagateDataChange()
{
//signal_DataChanged();
signal_DataChanged( boost::shared_ptr<WModuleConnector>(), shared_from_this() );
}
......@@ -29,7 +29,7 @@
#include <boost/shared_ptr.hpp>
// this seems to be necessary
// this is necessary since we have some kind of cyclic includes
template < typename T > class WModuleOutputData;
#include "WModuleInputData.hpp"
......@@ -54,6 +54,7 @@ public:
WModuleOutputData( boost::shared_ptr<WModule> module, std::string name="", std::string description="" ):
WModuleOutputConnector( module, name, description )
{
m_data = boost::shared_ptr<T>();
};
/**
......
......@@ -43,6 +43,7 @@
#include "../exceptions/WModuleConnectionFailed.h"
#include "../exceptions/WModuleConnectorsIncompatible.h"
#include "../exceptions/WModuleException.h"
#include "../exceptions/WModuleConnectorUnconnected.h"
/**
* Class implementing a simple mod // required since pure virtualule, since proper testing of WModuleConnector itself is not usable.
......@@ -104,6 +105,7 @@ public:
}
protected:
/**
* temporary name string
*/
......@@ -119,33 +121,45 @@ protected:
}
}
virtual void notifyConnectionEstablished( boost::shared_ptr<WModuleConnector> here,
boost::shared_ptr<WModuleConnector> there )
virtual void notifyConnectionEstablished( boost::shared_ptr<WModuleConnector> /*here*/,
boost::shared_ptr<WModuleConnector> /*there*/ )
{
// std::cout << "connection established between " << n << ":" << here->getCanonicalName() << " and "
// << there->getCanonicalName() << std::endl;
}
virtual void notifyConnectionClosed( boost::shared_ptr<WModuleConnector> here,
boost::shared_ptr<WModuleConnector> there )
virtual void notifyConnectionClosed( boost::shared_ptr<WModuleConnector> /*here*/,
boost::shared_ptr<WModuleConnector> /*there*/ )
{
// std::cout << "connection closed between " << n << ":" << here->getCanonicalName() << " and "
// << there->getCanonicalName() << std::endl;
}
virtual void notifyDataChange( boost::shared_ptr<WModuleConnector> /*input*/,
boost::shared_ptr<WModuleConnector> /*output*/ )
boost::shared_ptr<WModuleConnector> output )
{
std::cout << "hallo change" << std::endl;
// just copy the data
data=*( boost::shared_dynamic_cast<WModuleOutputData<int> >( output )->getData() ) + 1;
//std::cout << "change to " << data << " in " << input->getCanonicalName() << " from " << output->getCanonicalName() << std::endl;
}
private:
/**
* The data lastly submitted.
*/
int data;
/**
* Input connection.
*/
boost::shared_ptr<WModuleInputData<int> > m_Input;
/**
* Output connection.
*/
boost::shared_ptr<WModuleOutputData<int> > m_Output;
/*
boost::shared_ptr<WModuleInputConnector> m_Input;
boost::shared_ptr<WModuleOutputConnector> m_Output;*/
};
......@@ -243,6 +257,8 @@ public:
*/
void testModuleTwiceInitialization( void )
{
WException::disableBacktrace();
createModules();
initModules();
......@@ -261,6 +277,8 @@ public:
*/
void testModuleConnectorCompatibility( void )
{
WException::disableBacktrace();
createModules();
initModules();
......@@ -370,14 +388,41 @@ public:
}
/**
* Tests the signal handler management.
* Tests the propagation of data.
*/
void testModulePropagateDataChange( void )
{
createModules();
initModules();
initConnections();
// propagate change
// set some data, propagate change
int d=5;
TS_ASSERT_THROWS_NOTHING( m1->m_Output->updateData( boost::shared_ptr<int>( &d ) ) );
// got the data transferred?
TS_ASSERT( *(m1->m_Output->getData()) == d );
TS_ASSERT( *(m2->m_Input->getData()) == d );
TS_ASSERT( m2->data == d + 1 );
}
/**
* Tests several cases of unset data.
*/
void testModuleInvalidData( void )
{
WException::disableBacktrace();
createModules();
initModules();
initConnections();
// try to get data from an unconnected connector
TS_ASSERT_THROWS( m3->m_Input->getData(), WModuleConnectorUnconnected );
// try to get uninitialized data:
// should return an "NULL" Pointer
TS_ASSERT( m2->m_Input->getData() == boost::shared_ptr<int>() );
}
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment