From: g0dil Date: Tue, 30 Jun 2009 10:56:20 +0000 (+0000) Subject: PPI: Add user container support to MultiConnectorMixin X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=dadb96b3fcde947cec6587e2ea0998dee1c5740b;p=senf.git PPI: Add user container support to MultiConnectorMixin git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1250 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/PPI/MultiConnectorMixin.hh b/PPI/MultiConnectorMixin.hh index e63d7ff..a04be33 100644 --- a/PPI/MultiConnectorMixin.hh +++ b/PPI/MultiConnectorMixin.hh @@ -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 conn, unsigned p) + { + if (p>connectors_.size()) + throw SomeErrorException(); + route(*conn, output); + connectors_.insert(connectors_.begin()+p,conn); + } + + boost::ptr_vector 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 MultiConnectorMixin + : private detail::MultiConnectorSelectBase::type + { + public: + typedef ConnectorType_ ConnectorType; + + private: + +#if 0 + // For exposition only + // Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly + + tempalte + ConnectorType_ & newConnector(A1 const & a1); + + // See above for an additional note regarding the boost::enable_if in the real + // implementation + + template + friend Source::ConnectorType & senf::ppi::connect(Source & source, + Target & target, + A1 const & a1); + + template + 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 }}} diff --git a/PPI/MultiConnectorMixin.mpp b/PPI/MultiConnectorMixin.mpp index be0c920..121bf8c 100644 --- a/PPI/MultiConnectorMixin.mpp +++ b/PPI/MultiConnectorMixin.mpp @@ -102,6 +102,9 @@ connect(Source & source, Target & target mpp_FnParamsKomma()); // //////////////////////////////////////////////////////////////////////// // Implementation +//////////////////////////////////////// +// Map container + template mpp_TplParams() prefix_ ConnectorType_ & @@ -113,6 +116,9 @@ newConnector(mpp_FnParams()) return * connectors_.insert(key, conn).first->second; } +//////////////////////////////////////// +// Vector container + template mpp_TplParams() prefix_ ConnectorType_ & @@ -126,6 +132,24 @@ newConnector(mpp_FnParams()) return conn; } +//////////////////////////////////////// +// User managed container + +template +mpp_TplParams() +prefix_ ConnectorType_ & +senf::ppi::module::MultiConnectorMixin:: +newConnector(mpp_FnParams()) +{ + std::auto_ptr cp (new ConnectorType_); + ConnectorType_ & cref (*cp); + static_cast(this)->connectorSetup(cp mpp_CallParamsKomma()); + return cref; +} + +//////////////////////////////////////// +// senf::ppi::connect + template typename boost::enable_if< boost::is_base_of, diff --git a/PPI/MultiConnectorMixin.test.cc b/PPI/MultiConnectorMixin.test.cc index 34b76d5..bb81a69 100644 --- a/PPI/MultiConnectorMixin.test.cc +++ b/PPI/MultiConnectorMixin.test.cc @@ -27,7 +27,7 @@ //#include "MultiConnectorMixin.test.ih" // Custom includes -#include "MultiConnectorMixin.hh" +#include "PPI.hh" #include "../Utils/auto_unit_test.hh" #include @@ -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, + 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 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 Connectors; + Connectors connectors_; + + friend class senf::ppi::module::MultiConnectorMixin, + 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_