Skip to content
Snippets Groups Projects
Commit 0202f465 authored by g0dil's avatar g0dil
Browse files

PPI: Add user container support to MultiConnectorMixin

parent 13a3283c
No related branches found
No related tags found
No related merge requests found
......@@ -93,7 +93,8 @@ namespace module {
output connectors.
\code
class MyModule
: public senf::ppi::module::MultiConnectorMixin<
: public senf::ppi::module::Modulem,
public senf::ppi::module::MultiConnectorMixin<
MyModule, senf::ppi::connector::ActiveInput<> >
{
SENF_PPI_MODULE(MyModule);
......@@ -190,6 +191,39 @@ namespace module {
you need to pass a non-const reference, declare the \c connectorSetup() argument as
non-const reference and wrap the real argument using \c boost::ref() (The reason for
this is known as 'The forwarding problem'
\section Advanced usage: Managing your own container
If you need to use a completely different type of container, you can take over the container
management yourself. To do this, pass \c void as container type and change \c
connectorSetup() to take an \c std::auto_ptr as argument. \c connectorSetup() must ensure to
save this connector in some container or throw an exception
\code
class MyModule
: public senf::ppi::module::Modulem,
public senf::ppi::module::MultiConnectorMixin<
MyModule, senf::ppi::connector::ActiveInput<>, void, void >
{
SENF_PPI_MODULE(MyModule);
public:
// ...
private:
void connectorSetup(std::auto_ptr<ConnectorType> conn, unsigned p)
{
if (p>connectors_.size())
throw SomeErrorException();
route(*conn, output);
connectors_.insert(connectors_.begin()+p,conn);
}
boost::ptr_vector<ConnectorType> connectors_;
};
\endcode
\warning You must make absolutely sure the connector does not get deleted when returning
normally from \c connectorSetup(): The connector \e must be saved somewhere
successfully, otherwise your code will break.
*/
template <class Self_,
class ConnectorType_,
......@@ -292,6 +326,46 @@ namespace module {
ContainerType_ connectors_;
};
template <class Self_,
class ConnectorType_>
class MultiConnectorMixin<Self_,ConnectorType_,void,void>
: private detail::MultiConnectorSelectBase<ConnectorType_>::type
{
public:
typedef ConnectorType_ ConnectorType;
private:
#if 0
// For exposition only
// Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly
tempalte <class A1>
ConnectorType_ & newConnector(A1 const & a1);
// See above for an additional note regarding the boost::enable_if in the real
// implementation
template <class Source, class Target, class A1>
friend Source::ConnectorType & senf::ppi::connect(Source & source,
Target & target,
A1 const & a1);
template <class Source, class Target, class A1>
friend Target::ConnectorType & senf::ppi::connect(Source & source,
Target & target,
A1 const & a1);
#endif
// Include 'MultiConnectorMixin member declaration' from MultiConnectorMixin.mpp
# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
0, \
SENF_MULTI_CONNECTOR_MAX_ARGS, \
SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
1 ))
# include BOOST_PP_ITERATE()
};
#endif
}}}
......
......@@ -102,6 +102,9 @@ connect(Source & source, Target & target mpp_FnParamsKomma());
// ////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////
// Map container
template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
mpp_TplParams()
prefix_ ConnectorType_ &
......@@ -113,6 +116,9 @@ newConnector(mpp_FnParams())
return * connectors_.insert(key, conn).first->second;
}
////////////////////////////////////////
// Vector container
template <class Self_, class ConnectorType_, class ContainerType_>
mpp_TplParams()
prefix_ ConnectorType_ &
......@@ -126,6 +132,24 @@ newConnector(mpp_FnParams())
return conn;
}
////////////////////////////////////////
// User managed container
template <class Self_, class ConnectorType_>
mpp_TplParams()
prefix_ ConnectorType_ &
senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
newConnector(mpp_FnParams())
{
std::auto_ptr<ConnectorType_> cp (new ConnectorType_);
ConnectorType_ & cref (*cp);
static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
return cref;
}
////////////////////////////////////////
// senf::ppi::connect
template <class Source, class Target mpp_TplParamsKomma()>
typename boost::enable_if<
boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
......
......@@ -27,7 +27,7 @@
//#include "MultiConnectorMixin.test.ih"
// Custom includes
#include "MultiConnectorMixin.hh"
#include "PPI.hh"
#include "../Utils/auto_unit_test.hh"
#include <boost/test/test_tools.hpp>
......@@ -35,8 +35,73 @@
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
BOOST_AUTO_UNIT_TEST(dynamicConnectorMixin)
{}
namespace {
// We only test the user-collection case, all other cases are already handled by
// existing modules
// Primitive duplicator
class MyModule
: public senf::ppi::module::Module,
public senf::ppi::module::MultiConnectorMixin<MyModule,
senf::ppi::connector::ActiveOutput<>,
void, void>
{
SENF_PPI_MODULE(MyModule);
public:
senf::ppi::connector::PassiveInput<> input;
MyModule()
{
noroute(input);
input.onRequest(&MyModule::request);
}
private:
void connectorSetup(std::auto_ptr<ConnectorType> c)
{
route(input, *c);
connectors_.push_back(c);
}
void request()
{
senf::Packet p (input());
for (Connectors::iterator i (connectors_.begin()), i_end (connectors_.end());
i != i_end; ++i)
(*i)(p);
}
typedef boost::ptr_vector<MyModule::ConnectorType> Connectors;
Connectors connectors_;
friend class senf::ppi::module::MultiConnectorMixin<MyModule,
senf::ppi::connector::ActiveOutput<>,
void, void>;
};
}
BOOST_AUTO_UNIT_TEST(multiConnectorMixin_userContainer)
{
senf::ppi::module::debug::ActiveSource source;
MyModule module;
senf::ppi::module::debug::PassiveSink sink1;
senf::ppi::module::debug::PassiveSink sink2;
senf::ppi::connect(source, module);
senf::ppi::connect(module, sink1);
senf::ppi::connect(module, sink2);
senf::ppi::init();
senf::Packet p (senf::DataPacket::create());
source.submit(p);
BOOST_CHECK_EQUAL( sink1.size(), 1u );
BOOST_CHECK_EQUAL( sink2.size(), 1u );
BOOST_CHECK( sink1.pop_front() == p );
BOOST_CHECK( sink2.pop_front() == p );
}
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment