From: g0dil Date: Mon, 31 Aug 2009 23:29:06 +0000 (+0000) Subject: PPI: Allow connecting two MultiConnectorMixin modules X-Git-Url: http://g0dil.de/git?p=senf.git;a=commitdiff_plain;h=2d88e6b3f5a6f3906e42264f58859e6bf9c12dae PPI: Allow connecting two MultiConnectorMixin modules git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1360 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/SConstruct b/SConstruct index ff96d8d..6b55257 100644 --- a/SConstruct +++ b/SConstruct @@ -16,7 +16,6 @@ env = Environment() # Load all the local SCons tools env.Tool('Doxygen') -env.Tool('Doxygen') env.Tool('Dia2Png') env.Tool('PkgDraw') env.Tool('InstallSubdir') diff --git a/senf/PPI/MultiConnectorMixin.cti b/senf/PPI/MultiConnectorMixin.cti index 3df16d8..eabe309 100644 --- a/senf/PPI/MultiConnectorMixin.cti +++ b/senf/PPI/MultiConnectorMixin.cti @@ -110,6 +110,14 @@ senf::ppi::connect(Source & source, Target & target , A1 const & a1) 3 )) #include BOOST_PP_ITERATE() +// Include 'senf::ppi::detail implementation' from MultiConnectorMixin.mpp +#define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS2, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 7 )) +#include BOOST_PP_ITERATE() + #endif ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/senf/PPI/MultiConnectorMixin.hh b/senf/PPI/MultiConnectorMixin.hh index c154657..4e248ee 100644 --- a/senf/PPI/MultiConnectorMixin.hh +++ b/senf/PPI/MultiConnectorMixin.hh @@ -34,14 +34,15 @@ #include "Connectors.hh" #include "Setup.hh" -#include "MultiConnectorMixin.mpp" -#include "MultiConnectorMixin.ih" -///////////////////////////////hh.p//////////////////////////////////////// - #ifndef SENF_MULTI_CONNECTOR_MAX_ARGS #define SENF_MULTI_CONNECTOR_MAX_ARGS 3 +#define SENF_MULTI_CONNECTOR_MAX_ARGS2 6 #endif +#include "MultiConnectorMixin.mpp" +#include "MultiConnectorMixin.ih" +///////////////////////////////hh.p//////////////////////////////////////// + namespace senf { namespace ppi { @@ -73,9 +74,14 @@ namespace ppi { MultiConnectorTarget::ConnectorType & connect( Source & source, MultiConnectorTarget & target, A1 const & a1); + template + std::pair + connect( + MultiConnectorSource & source, MultiConnectorTarget & target, A1 const & a1, A2 const & a2); + #else - // Include 'senf::ppi::namespace member declarations' from MultiConnectorMixin.mpp + // Include 'senf::ppi namespace member declarations' from MultiConnectorMixin.mpp # define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ 0, \ SENF_MULTI_CONNECTOR_MAX_ARGS, \ @@ -83,10 +89,19 @@ namespace ppi { 2 )) # include BOOST_PP_ITERATE() +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS2, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 6 )) +# include BOOST_PP_ITERATE() + #endif namespace module { + namespace detail { class MultiConnectorMixinAccess; } + /** \brief Multi connector management This mixin provides a module with support for a runtime configurable number of input or @@ -249,18 +264,6 @@ namespace module { 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 #ifndef DOXYGEN @@ -272,7 +275,16 @@ namespace module { 1 )) # include BOOST_PP_ITERATE() +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS2, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 9 )) +# include BOOST_PP_ITERATE() + #endif + + friend class detail::MultiConnectorMixinAccess; ContainerType_ connectors_; }; @@ -323,6 +335,15 @@ namespace module { 1 )) # include BOOST_PP_ITERATE() +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS2, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 9 )) +# include BOOST_PP_ITERATE() + + friend class detail::MultiConnectorMixinAccess; + ContainerType_ connectors_; }; @@ -364,6 +385,15 @@ namespace module { SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ 1 )) # include BOOST_PP_ITERATE() + +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS2, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 9 )) +# include BOOST_PP_ITERATE() + + friend class detail::MultiConnectorMixinAccess; }; #endif diff --git a/senf/PPI/MultiConnectorMixin.ih b/senf/PPI/MultiConnectorMixin.ih index 0d96226..eff8769 100644 --- a/senf/PPI/MultiConnectorMixin.ih +++ b/senf/PPI/MultiConnectorMixin.ih @@ -35,6 +35,16 @@ namespace ppi { namespace module { namespace detail { + struct MultiConnectorMixinAccess + { +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 8 )) +# include BOOST_PP_ITERATE() + }; + template struct MultiConnectorDefaultContainer { @@ -58,6 +68,52 @@ namespace detail { ppi::detail::DisableStandardInput, ppi::detail::DisableStandardOutput > {}; + template senf::mpl::rv<0> is_multiconnector_(T *, ...); + template senf::mpl::rv<1> is_multiconnector_( + T *, + typename boost::enable_if, + int>::type); + template senf::mpl::rv<2> is_multiconnector_( + T *, + typename boost::enable_if, + int>::type); + + template + struct is_multiconnector_source_ + : public boost::false_type + {}; + + template + struct is_multiconnector_source_ + : public boost::true_type + {}; + + template + struct is_multiconnector_source + : public is_multiconnector_source_< + T, SENF_MPL_RV(is_multiconnector_(static_cast(0),0))> + {}; + + template + struct is_multiconnector_target_ + : public boost::false_type + {}; + + template + struct is_multiconnector_target_ + : public boost::true_type + {}; + + template + struct is_multiconnector_target + : public is_multiconnector_target_< + T, SENF_MPL_RV(is_multiconnector_(static_cast(0),0))> + {}; + + + }}}} ///////////////////////////////ih.e//////////////////////////////////////// diff --git a/senf/PPI/MultiConnectorMixin.mpp b/senf/PPI/MultiConnectorMixin.mpp index aeb5dfd..ac56abe 100644 --- a/senf/PPI/MultiConnectorMixin.mpp +++ b/senf/PPI/MultiConnectorMixin.mpp @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include // ///////////////////////////mpp.p//////////////////////////////////////// #elif BOOST_PP_IS_ITERATING // //////////////////////////////////////////// @@ -60,6 +63,18 @@ #define mpp_CallParamsKomma() \ BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a) +// Same as above but for outer loop in nested loops +#define mpp_TplParamsKomma2() \ + BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), class B) +#define mpp_FnParams2() \ + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & a) +#define mpp_FnParamsKomma2() \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & b) +#define mpp_CallParams2() \ + BOOST_PP_ENUM_PARAMS(BOOST_PP_FRAME_ITERATION(1), b) +#define mpp_CallParamsKomma2() \ + BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), b) + // //////////////////////////////////////////////////////////////////////// #if BOOST_PP_ITERATION_FLAGS()==1 // ////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// @@ -68,35 +83,74 @@ mpp_TplParams() ConnectorType_ & newConnector( mpp_FnParams() ); -template -friend typename boost::enable_if< - boost::is_base_of, - typename Source::ConnectorType & >::type - senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()); +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==9 // ////////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// MultiConnectorMixin member declaration template -friend typename boost::enable_if< - boost::is_base_of, - typename Target::ConnectorType & >::type - senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()); +static std::pair +connect_(Source & source, Target & target mpp_FnParamsKomma()); // //////////////////////////////////////////////////////////////////////// #elif BOOST_PP_ITERATION_FLAGS()==2 // //////////////////////////////////// // //////////////////////////////////////////////////////////////////////// // senf::ppi namespace member declaration +// Here the reference to Source::ConnectorType / Target::ConnectorType +// works like enable_if, since only MultiConnector modules have those members + template typename boost::enable_if< - boost::is_base_of, + boost::mpl::and_< + senf::ppi::module::detail::is_multiconnector_source, + boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_target > >, typename Source::ConnectorType & >::type connect(Source & source, Target & target mpp_FnParamsKomma()); template typename boost::enable_if< - boost::is_base_of, + boost::mpl::and_< + boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_source >, + senf::ppi::module::detail::is_multiconnector_target >, typename Target::ConnectorType & >::type connect(Source & source, Target & target mpp_FnParamsKomma()); +#define BOOST_PP_ITERATION_PARAMS_2 (4, (\ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 4 )) +#include BOOST_PP_ITERATE() + +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==6 // //////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// senf::ppi namespace member declaration (nested) + +template +typename boost::enable_if< + boost::mpl::and_< + boost::is_base_of, + boost::is_base_of >, + std::pair >::type +connect(Source & source, Target & target mpp_FnParamsKomma()); + +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==4 // //////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// senf::ppi::detail namespace member declaration (nested iteration) + +namespace detail { + +template +typename boost::enable_if_c< + senf::function_arity::value == BOOST_PP_ITERATION()+1, + std::pair >::type +connect_(Fn, Source & source, Target & target mpp_FnParamsKomma() mpp_FnParamsKomma2()); + +} + // //////////////////////////////////////////////////////////////////////// #elif BOOST_PP_ITERATION_FLAGS()==3 // //////////////////////////////////// // //////////////////////////////////////////////////////////////////////// @@ -148,35 +202,152 @@ newConnector(mpp_FnParams()) } //////////////////////////////////////// +// senf::ppi::module::detail::MultiConnectorMixinAccess members + +template +typename Module::ConnectorType & +senf::ppi::module::detail::MultiConnectorMixinAccess::newConnector( + Module & module mpp_FnParamsKomma()) +{ + return module.newConnector(mpp_CallParams()); +} + +template +std::pair +senf::ppi::module::detail::MultiConnectorMixinAccess::connect( + Source & source, Target & target mpp_FnParamsKomma()) +{ + return Source::connect_(source, target mpp_CallParamsKomma()); +} + +//////////////////////////////////////// // senf::ppi::connect template typename boost::enable_if< - boost::is_base_of, + boost::mpl::and_< + senf::ppi::module::detail::is_multiconnector_source, + boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_target > >, typename Source::ConnectorType & >::type senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()) { - typename Source::ConnectorType & c (source.newConnector(mpp_CallParams())); + typename Source::ConnectorType & c ( + module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma())); connect(c, target); return c; } template typename boost::enable_if< - boost::is_base_of, + boost::mpl::and_< + boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_source >, + senf::ppi::module::detail::is_multiconnector_target >, typename Target::ConnectorType & >::type senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()) { - typename Target::ConnectorType & c (target.newConnector(mpp_CallParams())); + typename Target::ConnectorType & c ( + module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma())); connect(source, c); return c; } +#define BOOST_PP_ITERATION_PARAMS_2 (4, (\ + 0, \ + SENF_MULTI_CONNECTOR_MAX_ARGS, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \ + 5 )) +#include BOOST_PP_ITERATE() + +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==5 // //////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// Implementation for nested iteration + +template +typename boost::enable_if_c< + senf::function_arity::value == BOOST_PP_ITERATION()+1, + std::pair >::type +senf::ppi::detail::connect_(Fn, Source & source, Target & target + mpp_FnParamsKomma() mpp_FnParamsKomma2()) +{ + typename Source::ConnectorType & s ( + module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma())); + typename Target::ConnectorType & t ( + module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma2())); + connect(s,t); + return std::pair(s,t); +} + +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==7 // //////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// Implementation + +template +template +std::pair +senf::ppi::module::MultiConnectorMixin:: +connect_(Source & source, Target & target mpp_FnParamsKomma()) +{ + return senf::ppi::detail::connect_( + & Self_::connectorSetup, source, target mpp_CallParamsKomma()); +} + +template +template +std::pair +senf::ppi::module::MultiConnectorMixin:: +connect_(Source & source, Target & target mpp_FnParamsKomma()) +{ + return senf::ppi::detail::connect_( + & Self_::connectorSetup, source, target mpp_CallParamsKomma()); +} + +template +template +std::pair +senf::ppi::module::MultiConnectorMixin:: +connect_(Source & source, Target & target mpp_FnParamsKomma()) +{ + return senf::ppi::detail::connect_( + & Self_::connectorSetup, source, target mpp_CallParamsKomma()); +} + +template +typename boost::enable_if< + boost::mpl::and_< + boost::is_base_of, + boost::is_base_of >, + std::pair >::type +senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()) +{ + return module::detail::MultiConnectorMixinAccess::connect( + source, target mpp_CallParamsKomma()); +} + +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==8 // //////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// senf::ppi::module::detail::MultiConnectorMixinAccess members + +template +static typename Module::ConnectorType & +newConnector(Module & module mpp_FnParamsKomma()); + +template +static std::pair +connect(Source & source, Target & target mpp_FnParamsKomma()); + // //////////////////////////////////////////////////////////////////////// #endif // ///////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// // Undefine local Macros +#undef mpp_CallParamsKomma2 +#undef mpp_CallParams2 +#undef mpp_FnParamsKomma2 +#undef mpp_FnParams2 +#undef mpp_TplParamsKomma2 #undef mpp_CallParamsKomma #undef mpp_CallParams #undef mpp_FnParamsKomma @@ -196,7 +367,7 @@ senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()) (search-backward "#define") (forward-line 1) (point))))) (point)))) (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert - "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z_]") + "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z0-9_]") (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line 1)))) */ diff --git a/senf/PPI/MultiConnectorMixin.test.cc b/senf/PPI/MultiConnectorMixin.test.cc index 83f6532..44d6402 100644 --- a/senf/PPI/MultiConnectorMixin.test.cc +++ b/senf/PPI/MultiConnectorMixin.test.cc @@ -91,6 +91,13 @@ namespace { { os << value.value; return os; } } +BOOST_AUTO_UNIT_TEST(multiConnectorTraits) +{ + BOOST_STATIC_ASSERT( senf::ppi::module::detail::is_multiconnector_source::value ); + BOOST_STATIC_ASSERT( ! senf::ppi::module::detail::is_multiconnector_target::value ); +} + + BOOST_AUTO_UNIT_TEST(multiConnectorMixin_userContainer) { debug::ActiveSource source; @@ -114,8 +121,6 @@ BOOST_AUTO_UNIT_TEST(multiConnectorMixin_userContainer) BOOST_AUTO_UNIT_TEST(multiConnectorMixin_multipleModules) { - // This test fails! - /* debug::ActiveSource source; debug::PassiveSink sink; module::PassiveJoin join1; @@ -135,7 +140,6 @@ BOOST_AUTO_UNIT_TEST(multiConnectorMixin_multipleModules) source.submit(p); BOOST_CHECK_EQUAL( sink.size(), 1u ); BOOST_CHECK( sink.pop_front() == p ); - */ } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/senf/PPI/Setup.cti b/senf/PPI/Setup.cti index ca6e672..7245c5c 100644 --- a/senf/PPI/Setup.cti +++ b/senf/PPI/Setup.cti @@ -58,8 +58,8 @@ prefix_ void senf::ppi:: connect(T1 & source, T2 & target, typename boost::disable_if< boost::is_base_of >::type *, typename boost::disable_if< boost::is_base_of >::type *, - typename boost::disable_if< boost::is_base_of >:: type *, - typename boost::disable_if< boost::is_base_of >:: type *) + typename boost::disable_if< boost::is_base_of >::type *, + typename boost::disable_if< boost::is_base_of >::type *) { connect(source.output, target.input); } diff --git a/senf/Utils/type_traits.hh b/senf/Utils/type_traits.hh index a728ac0..8f58122 100644 --- a/senf/Utils/type_traits.hh +++ b/senf/Utils/type_traits.hh @@ -243,6 +243,14 @@ namespace senf : public boost::remove_cv< typename boost::remove_reference::type > {}; + template < class T > + struct function_arity + : public boost::integral_constant< + unsigned, + boost::function_traits< + typename senf::remove_any_pointer::type>::arity> + {}; + ///} #ifndef DOXYGEN diff --git a/senf/Utils/type_traits.test.cc b/senf/Utils/type_traits.test.cc index c446157..fb9fe5f 100644 --- a/senf/Utils/type_traits.test.cc +++ b/senf/Utils/type_traits.test.cc @@ -103,6 +103,13 @@ BOOST_AUTO_UNIT_TEST(typeTraits) senf::remove_cvref::type, int >::value )); + + BOOST_STATIC_ASSERT(( senf::function_arity::value == 0 )); + BOOST_STATIC_ASSERT(( senf::function_arity::value == 2 )); + BOOST_STATIC_ASSERT(( senf::function_arity::value == 0 )); + BOOST_STATIC_ASSERT(( senf::function_arity::value == 2 )); + BOOST_STATIC_ASSERT(( senf::function_arity::value == 0 )); + BOOST_STATIC_ASSERT(( senf::function_arity::value == 2 )); } ///////////////////////////////cc.e////////////////////////////////////////