diff --git a/PPI/AnnotationRouter.ct b/PPI/AnnotationRouter.ct index bef2f9c48752fef659fa9ba24bc175e9d57b2407..62311647880b4272edfebf20e376aba9bcfb160d 100644 --- a/PPI/AnnotationRouter.ct +++ b/PPI/AnnotationRouter.ct @@ -39,30 +39,22 @@ prefix_ senf::ppi::module::AnnotationRouter<AnnotationType>::AnnotationRouter() } template <class AnnotationType> -prefix_ senf::ppi::connector::ActiveOutput<> & -senf::ppi::module::AnnotationRouter<AnnotationType>::newOutput(AnnotationType const & key) +prefix_ AnnotationType senf::ppi::module::AnnotationRouter<AnnotationType>:: +connectorSetup(connector::ActiveOutput<> & conn, AnnotationType const & key) { - if (outputs_.find(key) != outputs_.end()) + if (this->connectors().find(key) != this->connectors().end()) throw DuplicateKeyException(key); - // key must not be const ... has something to do with exception guarantees ?? - // From boost 1.34.0 on we can use auto_ptr which we really should for exception safety - // but this doesn't work with boost 1.33.1 :-( -#if BOOST_VERSION >= 103400 - return *outputs_.insert(key, - std::auto_ptr<connector::ActiveOutput<> >( - new connector::ActiveOutput<>())).first->second; -#else - AnnotationType k (key); - return *outputs_.insert(k, new connector::ActiveOutput<>()).first; -#endif + route(input, conn); + return key; } template <class AnnotationType> prefix_ void senf::ppi::module::AnnotationRouter<AnnotationType>::request() { Packet p (input()); - typename Outputs::iterator i (outputs_.find(p.annotation<AnnotationType>())); - if (i == outputs_.end()) + typename AnnotationRouter::DynamicConnectorContainer::iterator i ( + this->connectors().find(p.annotation<AnnotationType>())); + if (i == this->connectors().end()) defaultOutput(p); else { #if BOOST_VERSION >= 103400 diff --git a/PPI/AnnotationRouter.hh b/PPI/AnnotationRouter.hh index 705eb8dab9406163b9abc4d863008d88e426550f..7badaaf21dca7fa1910134da24dae666b8ee5f7b 100644 --- a/PPI/AnnotationRouter.hh +++ b/PPI/AnnotationRouter.hh @@ -31,6 +31,7 @@ #include "../Utils/String.hh" #include "Module.hh" #include "Connectors.hh" +#include "DynamicConnectorMixin.hh" //#include "AnnotationRouter.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -93,7 +94,11 @@ namespace module { from the container */ template <class AnnotationType> - class AnnotationRouter : public Module + class AnnotationRouter + : public Module, + public DynamicConnectorMixin< AnnotationRouter<AnnotationType>, + connector::ActiveOutput<>, + AnnotationType > { SENF_PPI_MODULE(AnnotationRouter); public: @@ -108,39 +113,23 @@ namespace module { { append( senf::str(key)); } }; private: - connector::ActiveOutput<> & newOutput(AnnotationType const & key); - -#ifndef DOXYGEN - // I didn't get template friend functions to work ... - public: -#endif - template <class Target> - connector::GenericActiveOutput & connect(Target & target, AnnotationType const & key); - - private: + AnnotationType connectorSetup(connector::ActiveOutput<> & conn, AnnotationType const & key); void request(); typedef boost::ptr_map<AnnotationType, connector::ActiveOutput<> > Outputs; Outputs outputs_; - }; -} - -#ifndef DOXYGEN - - template <class Target, class AnnotationType, class ArgType> - connector::GenericActiveOutput & connect( - module::AnnotationRouter<AnnotationType> & source, Target & target, - ArgType const & key); - -#endif + friend class DynamicConnectorMixin< AnnotationRouter<AnnotationType>, + connector::ActiveOutput<>, + AnnotationType >; + }; -}} +}}} ///////////////////////////////hh.e//////////////////////////////////////// //#include "AnnotationRouter.cci" #include "AnnotationRouter.ct" -#include "AnnotationRouter.cti" +//#include "AnnotationRouter.cti" #endif diff --git a/PPI/Duplicators.cc b/PPI/Duplicators.cc index f62679d4c8c8b0ef46f15247cd624924ba59fbc5..b6dd077397a19f764fb972be9a08c39f710c757c 100644 --- a/PPI/Duplicators.cc +++ b/PPI/Duplicators.cc @@ -32,22 +32,17 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -prefix_ senf::ppi::connector::ActiveOutput<> & -senf::ppi::module::ActiveDuplicator::newOutput() +prefix_ void +senf::ppi::module::ActiveDuplicator::connectorSetup(ActiveDuplicator::DynamicConnector & conn) { - outputs_.push_back(new connector::ActiveOutput<>()); - connector::ActiveOutput<> & output (outputs_.back()); - - route(input, output); - - return output; + route(input, conn); } prefix_ void senf::ppi::module::ActiveDuplicator::request() { Packet p (input()); - Outputs::iterator i (outputs_.begin()); - Outputs::iterator const i_end (outputs_.end()); + ActiveDuplicator::ConnectorContainer::iterator i (connectors().begin()); + ActiveDuplicator::ConnectorContainer::iterator const i_end (connectors().end()); for (; i != i_end; ++i) (*i)(p); } diff --git a/PPI/Duplicators.hh b/PPI/Duplicators.hh index f5ea38936a5d4bd942ae84155a389141777ceb22..fea0a46f0a770bd1c11bbdf97ccd8a32987038df 100644 --- a/PPI/Duplicators.hh +++ b/PPI/Duplicators.hh @@ -31,20 +31,13 @@ #include "predecl.hh" #include "Connectors.hh" #include "Module.hh" +#include "DynamicConnectorMixin.hh" //#include "Duplicators.mpp" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { namespace ppi { - -#ifndef DOXYGEN - - template <class Target> - connector::GenericActiveOutput & connect(module::ActiveDuplicator & source, Target & target); - -#endif - namespace module { /** \brief Copy every incoming packet to each output @@ -65,7 +58,8 @@ namespace module { \ingroup routing_modules */ class ActiveDuplicator - : public Module + : public Module, + public DynamicConnectorMixin<ActiveDuplicator, connector::ActiveOutput<> > { SENF_PPI_MODULE(ActiveDuplicator); public: @@ -74,19 +68,10 @@ namespace module { ActiveDuplicator(); private: - connector::ActiveOutput<> & newOutput(); - -#ifndef DOXYGEN - public: -#endif - template <class Target> - connector::GenericActiveOutput & connect(Target & target); - - private: + void connectorSetup(ActiveDuplicator::DynamicConnector & conn); void request(); - typedef boost::ptr_vector<connector::ActiveOutput<> > Outputs; - Outputs outputs_; + friend class DynamicConnectorMixin<ActiveDuplicator, connector::ActiveOutput<> >; }; }}} @@ -96,7 +81,7 @@ namespace module { ///////////////////////////////hh.e//////////////////////////////////////// #include "Duplicators.cci" //#include "Duplicators.ct" -#include "Duplicators.cti" +//#include "Duplicators.cti" #endif diff --git a/PPI/Duplicators.cti b/PPI/DynamicConnectorMixin.cti similarity index 64% rename from PPI/Duplicators.cti rename to PPI/DynamicConnectorMixin.cti index fb9e74fb79951b6a1336dfc90b1b455e15db1910..97742b20fff9ea03fb2e1ef948644335e697f76c 100644 --- a/PPI/Duplicators.cti +++ b/PPI/DynamicConnectorMixin.cti @@ -21,32 +21,35 @@ // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** \file - \brief Duplicators inline template implementation */ + \brief DynamicConnectorMixin inline template implementation */ -//#include "Duplicators.ih" +//#include "DynamicConnectorMixin.ih" // Custom includes -#include "Setup.hh" #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// -template <class Target> -prefix_ senf::ppi::connector::GenericActiveOutput & -senf::ppi::connect(module::ActiveDuplicator & source, Target & target) +template <class Self, class ConnectorType, class KeyType, class ContainerType> +prefix_ ContainerType & +senf::ppi::module::DynamicConnectorMixin<Self,ConnectorType,KeyType,ContainerType>::connectors() { - return source.connect(target); + return connectors_; } -template <class Target> -prefix_ senf::ppi::connector::GenericActiveOutput & -senf::ppi::module::ActiveDuplicator::connect(Target & target) +template <class Self, class ConnectorType, class ContainerType> +prefix_ ContainerType & +senf::ppi::module::DynamicConnectorMixin<Self, ConnectorType, void, ContainerType>::connectors() { - connector::GenericActiveOutput & output (newOutput()); - ppi::connect(output, target); - return output; + return connectors_; } +#define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_DYNAMIC_CONNECTOR_MAX_ARGS, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/DynamicConnectorMixin.mpp), \ + 3 )) +#include BOOST_PP_ITERATE() ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/PPI/DynamicConnectorMixin.hh b/PPI/DynamicConnectorMixin.hh new file mode 100644 index 0000000000000000000000000000000000000000..996dc05fa4add3b3b066d7de87fa803c2110de10 --- /dev/null +++ b/PPI/DynamicConnectorMixin.hh @@ -0,0 +1,160 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund <g0dil@berlios.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief DynamicConnectorMixin public header */ + +#ifndef HH_SENF_PPI_DynamicConnectorMixin_ +#define HH_SENF_PPI_DynamicConnectorMixin_ 1 + +// Custom includes +#include "../config.hh" +#include <boost/ptr_container/ptr_map.hpp> +#include <boost/ptr_container/ptr_vector.hpp> +#include <boost/mpl/if.hpp> +#include "Connectors.hh" +#include "Setup.hh" + +#include "DynamicConnectorMixin.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +#ifndef SENF_DYNAMIC_CONNECTOR_MAX_ARGS +#define SENF_DYNAMIC_CONNECTOR_MAX_ARGS 3 +#endif + +namespace senf { +namespace ppi { + +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_DYNAMIC_CONNECTOR_MAX_ARGS, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/DynamicConnectorMixin.mpp), \ + 2 )) +# include BOOST_PP_ITERATE() + +namespace module { + +namespace detail { + template <class KeyType, class ConnectorType> + struct DefaultDynamicContainer + { typedef boost::ptr_map<KeyType, ConnectorType> type; }; + + template <class ConnectorType> + struct DefaultDynamicContainer<void,ConnectorType> + { typedef boost::ptr_vector<ConnectorType> type; }; + + template <class ConnectorType> + struct DynamicDisableType + : public boost::mpl::if_< + boost::is_base_of<connector::InputConnector, ConnectorType>, + ppi::detail::DisableStandardInput, ppi::detail::DisableStandardOutput > + {}; +} + + /** \brief Dynamic connector management + + Provide modules with support for dynamic connectors. + + \li A module might have dynamic input or output connectors + \li Creating a new connection might take an argument + \li Connectors are stored either in a vector or a map + + Workflow: + \li Connectors are created by the helper. + \li Connector is passed to Self::connectorSetup. This returns either void or the map + key. connectorSetup must setup internal routing and callbacks. + \li Connector inserted into container. + + connectorSetup may take additional arguments besides reference to connector. These arguments + are taken from the trailing ppi::connect call arguments. + + The list manager will insert the new connector at the end of the list BEFORE calling + connetorSetup. This allows the setup routine to manipulate the position. + */ + template <class Self, + class ConnectorType, + class KeyType=void, + class ContainerType=typename detail::DefaultDynamicContainer< + KeyType,ConnectorType>::type> + class DynamicConnectorMixin + : private detail::DynamicDisableType<ConnectorType>::type + { + public: + typedef ConnectorType DynamicConnector; + + protected: + typedef ContainerType DynamicConnectorContainer; + ContainerType & connectors(); + + private: +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_DYNAMIC_CONNECTOR_MAX_ARGS, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/DynamicConnectorMixin.mpp), \ + 1 )) +# include BOOST_PP_ITERATE() + + ContainerType connectors_; + }; + + template <class Self, + class ConnectorType, + class ContainerType> + class DynamicConnectorMixin<Self, ConnectorType, void, ContainerType> + : private detail::DynamicDisableType<ConnectorType>::type + { + public: + typedef ConnectorType DynamicConnector; + + protected: + typedef ContainerType ConnectorContainer; + ContainerType & connectors(); + + private: +# define BOOST_PP_ITERATION_PARAMS_1 (4, ( \ + 0, \ + SENF_DYNAMIC_CONNECTOR_MAX_ARGS, \ + SENF_ABSOLUTE_INCLUDE_PATH(PPI/DynamicConnectorMixin.mpp), \ + 1 )) +# include BOOST_PP_ITERATE() + + ContainerType connectors_; + }; + +}}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "DynamicConnectorMixin.cci" +//#include "DynamicConnectorMixin.ct" +#include "DynamicConnectorMixin.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/DynamicConnectorMixin.mpp b/PPI/DynamicConnectorMixin.mpp new file mode 100644 index 0000000000000000000000000000000000000000..19d6b8c3fef45ffbfacc19b2ee233a317c9125c7 --- /dev/null +++ b/PPI/DynamicConnectorMixin.mpp @@ -0,0 +1,188 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund <g0dil@berlios.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief DynamicConnectorMixin Boost.Preprocesser external iteration include */ + +#if !BOOST_PP_IS_ITERATING && !defined(MPP_SENF_PPI_DynamicConnectorMixin_) +#define MPP_SENF_PPI_DynamicConnectorMixin_ 1 + +// Custom includes +#include <boost/preprocessor/iteration/iterate.hpp> +#include <boost/preprocessor/control/if.hpp> +#include <boost/preprocessor/facilities/empty.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> +#include <boost/type_traits/is_base_of.hpp> + +// ///////////////////////////mpp.p//////////////////////////////////////// +#elif BOOST_PP_IS_ITERATING // //////////////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// Local Macros + +#define mpp_TplParams() \ + BOOST_PP_IF( \ + BOOST_PP_ITERATION(), \ + mpp_TplParams_, \ + BOOST_PP_EMPTY)() +#define mpp_TplParams_() \ + template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)> + +#define mpp_TplParamsKomma() \ + BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A) +#define mpp_FnParams() \ + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a) +#define mpp_FnParamsKomma() \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a) +#define mpp_CallParams() \ + BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a) +#define mpp_CallParamsKomma() \ + BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a) + +// //////////////////////////////////////////////////////////////////////// +#if BOOST_PP_ITERATION_FLAGS()==1 // ////////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// DynamicConnectorMixin member declaration + +mpp_TplParams() +ConnectorType & newConnector( mpp_FnParams() ); + +template <class Source, class Target mpp_TplParamsKomma()> +friend typename boost::enable_if< + boost::is_base_of<connector::OutputConnector, typename Source::DynamicConnector>, + typename Source::DynamicConnector & >::type + senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()); + +template <class Source, class Target mpp_TplParamsKomma()> +friend typename boost::enable_if< + boost::is_base_of<connector::InputConnector, typename Target::DynamicConnector>, + typename Target::DynamicConnector & >::type + senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()); + +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==2 // //////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// senf::ppi namespace member declaration + +template <class Source, class Target mpp_TplParamsKomma()> +typename boost::enable_if< + boost::is_base_of<connector::OutputConnector, typename Source::DynamicConnector>, + typename Source::DynamicConnector & >::type +connect(Source & source, Target & target mpp_FnParamsKomma()); + +template <class Source, class Target mpp_TplParamsKomma()> +typename boost::enable_if< + boost::is_base_of<connector::InputConnector, typename Target::DynamicConnector>, + typename Target::DynamicConnector & >::type +connect(Source & source, Target & target mpp_FnParamsKomma()); + +// //////////////////////////////////////////////////////////////////////// +#elif BOOST_PP_ITERATION_FLAGS()==3 // //////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// Implementation + +template <class Self, class ConnectorType, class KeyType, class ContainerType> +mpp_TplParams() +prefix_ ConnectorType & +senf::ppi::module::DynamicConnectorMixin<Self,ConnectorType,KeyType,ContainerType>:: +newConnector(mpp_FnParams()) +{ + std::auto_ptr<ConnectorType> conn (new ConnectorType); + KeyType key (static_cast<Self*>(this)->connectorSetup(*conn mpp_CallParamsKomma())); + return * connectors_.insert(key, conn).first->second; +} + +template <class Self, class ConnectorType, class ContainerType> +mpp_TplParams() +prefix_ ConnectorType & +senf::ppi::module::DynamicConnectorMixin<Self,ConnectorType,void,ContainerType>:: +newConnector(mpp_FnParams()) +{ + connectors_.push_back(new ConnectorType); + ConnectorType & conn (connectors_.back()); + try { static_cast<Self*>(this)->connectorSetup(conn mpp_CallParamsKomma()); } + catch (...) { connectors_.pop_back(); throw; } + return conn; +} + +template <class Source, class Target mpp_TplParamsKomma()> +typename boost::enable_if< + boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::DynamicConnector>, + typename Source::DynamicConnector & >::type +senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()) +{ + connect(source.newConnector(mpp_CallParams()), target); +} + +template <class Source, class Target mpp_TplParamsKomma()> +typename boost::enable_if< + boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::DynamicConnector>, + typename Target::DynamicConnector & >::type +senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma()) +{ + connect(source, target.newConnector(mpp_CallParams())); +} + +// //////////////////////////////////////////////////////////////////////// +#endif // ///////////////////////////////////////////////////////////////// +// //////////////////////////////////////////////////////////////////////// +// Undefine local Macros + +#undef mpp_CallParamsKomma +#undef mpp_CallParams +#undef mpp_FnParamsKomma +#undef mpp_FnParams +#undef mpp_TplParamsKomma +#undef mpp_TplParams_ +#undef mpp_TplParams + +// //////////////////////////////////////////////////////////////////////// +/* + (save-excursion (re-search-backward "^// Undefine local Macros") + (forward-line 1) (delete-region (point) (progn (search-forward + "// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point)) + (e (progn (insert (save-excursion (re-search-backward + "^// Local Macros") (search-forward "#define") (beginning-of-line) + (buffer-substring (point) (progn (search-forward "// ////") + (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_]") + (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line + 1)))) +*/ +// //////////////////////////////////////////////////////////////////////// +#endif // ///////////////////////////////////////////////////////////////// +// ///////////////////////////mpp.e//////////////////////////////////////// + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/AnnotationRouter.cti b/PPI/DynamicConnectorMixin.test.cc similarity index 53% rename from PPI/AnnotationRouter.cti rename to PPI/DynamicConnectorMixin.test.cc index d61468c8bc674597318d91db367bd187120b067e..9eb5c3d0c1eb2c78985b9f1b3f4959def2f5da7c 100644 --- a/PPI/AnnotationRouter.cti +++ b/PPI/DynamicConnectorMixin.test.cc @@ -1,6 +1,6 @@ // $Id$ // -// Copyright (C) 2008 +// Copyright (C) 2009 // Fraunhofer Institute for Open Communication Systems (FOKUS) // Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund <g0dil@berlios.de> @@ -21,41 +21,24 @@ // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** \file - \brief AnnotationRouter inline template implementation */ + \brief DynamicConnectorMixin.test unit tests */ -//#include "AnnotationRouter.ih" +//#include "DynamicConnectorMixin.test.hh" +//#include "DynamicConnectorMixin.test.ih" // Custom includes -#include "Setup.hh" +#include "DynamicConnectorMixin.hh" -#define prefix_ inline -///////////////////////////////cti.p/////////////////////////////////////// +#include "../Utils/auto_unit_test.hh" +#include <boost/test/test_tools.hpp> -template <class AnnotationType> -template <class Target> -prefix_ senf::ppi::connector::GenericActiveOutput & -senf::ppi::module::AnnotationRouter<AnnotationType>::connect(Target & target, - AnnotationType const & key) -{ - connector::GenericActiveOutput & output (newOutput(key)); - route(input, output); - ppi::connect(output, target); - return output; -} +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// -#ifndef DOXYGEN +BOOST_AUTO_UNIT_TEST(dynamicConnectorMixin) +{} -template <class Target, class AnnotationType, class ArgType> -prefix_ senf::ppi::connector::GenericActiveOutput & -senf::ppi::connect(module::AnnotationRouter<AnnotationType> & source, Target & target, - ArgType const & key) -{ - return source.connect(target, AnnotationType(key)); -} - -#endif - -///////////////////////////////cti.e/////////////////////////////////////// +///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/PPI/Jack.hh b/PPI/Jack.hh index 52c6b82fcf93250ecbd282ca5f146d0aae419523..a47d15d8e8a6481620825b1060acff7abc705f3e 100644 --- a/PPI/Jack.hh +++ b/PPI/Jack.hh @@ -30,6 +30,7 @@ #include <boost/utility.hpp> #include <boost/type_traits.hpp> #include "Connectors.hh" +#include "Setup.hh" //#include "Jack.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -41,7 +42,7 @@ namespace connector { /** \brief Connector Jack base class \see \ref ppi_jacks */ class Jack - : private boost::noncopyable + : private boost::noncopyable, private ppi::detail::DisableStandardConnect {}; /** \brief Jack referencing an ActiveInput diff --git a/PPI/Joins.cc b/PPI/Joins.cc index b8ce2d6763db2e95440f7d2915d3822b78efda6f..2ecccf36e900dbeb0fcf3a4aac466e5e22ea3c25 100644 --- a/PPI/Joins.cc +++ b/PPI/Joins.cc @@ -42,15 +42,10 @@ //////////////////////////////////////// // private members -prefix_ senf::ppi::connector::PassiveInput<> & senf::ppi::module::PassiveJoin::newInput() +prefix_ void senf::ppi::module::PassiveJoin::connectorSetup(connector::PassiveInput<> & conn) { - inputs_.push_back(new connector::PassiveInput<>()); - connector::PassiveInput<> & input (inputs_.back()); - - noroute(input); - input.onRequest(boost::bind(&PassiveJoin::request,this,boost::ref(input))); - - return input; + noroute(conn); + conn.onRequest(boost::bind(&PassiveJoin::request,this,boost::ref(conn))); } prefix_ void senf::ppi::module::PassiveJoin::request(connector::GenericPassiveInput & input) @@ -62,7 +57,7 @@ prefix_ void senf::ppi::module::PassiveJoin::onThrottle() { using boost::lambda::_1; using boost::lambda::bind; - std::for_each(inputs_.begin(), inputs_.end(), + std::for_each(connectors().begin(), connectors().end(), bind(&connector::GenericPassiveInput::throttle, _1)); } @@ -70,7 +65,7 @@ prefix_ void senf::ppi::module::PassiveJoin::onUnthrottle() { using boost::lambda::_1; using boost::lambda::bind; - std::for_each(inputs_.begin(), inputs_.end(), + std::for_each(connectors().begin(), connectors().end(), bind(&connector::GenericPassiveInput::unthrottle, _1)); } @@ -80,41 +75,40 @@ prefix_ void senf::ppi::module::PassiveJoin::onUnthrottle() //////////////////////////////////////// // private members -prefix_ senf::ppi::connector::ActiveInput<> & -senf::ppi::module::PriorityJoin::newInput(int priority) +prefix_ void +senf::ppi::module::PriorityJoin::connectorSetup(PriorityJoin::DynamicConnector & conn, + int priority) { - if (priority > int(inputs_.size())) - priority = inputs_.size(); - else if (priority < 0) { - priority = inputs_.size() + priority + 1; + noroute(conn); + conn.onThrottle(&PriorityJoin::onThrottle); + conn.onUnthrottle(&PriorityJoin::onUnthrottle); + + if (priority < 0) { + priority = connectors().size() + priority; if (priority < 0) priority = 0; } - - connector::ActiveInput<> & input ( - *inputs_.insert(inputs_.begin()+priority, new connector::ActiveInput<>())); - - noroute(input); - input.onThrottle(&PriorityJoin::onThrottle); - input.onUnthrottle(&PriorityJoin::onUnthrottle); - - return input; + if (priority >= int(connectors().size())-1) + return; + + connectors().insert(connectors().begin()+priority, connectors().pop_back().release()); } prefix_ void senf::ppi::module::PriorityJoin::request() { using boost::lambda::_1; using boost::lambda::bind; - Inputs::iterator i (std::find_if(inputs_.begin(), inputs_.end(), - ! bind(&connector::GenericActiveInput::throttled, _1))); - if (i != inputs_.end()) + PriorityJoin::ConnectorContainer::iterator i ( + std::find_if(connectors().begin(), connectors().end(), + ! bind(&connector::GenericActiveInput::throttled, _1))); + if (i != connectors().end()) output((*i)()); } prefix_ void senf::ppi::module::PriorityJoin::onThrottle() { - if (std::find_if(inputs_.begin(), inputs_.end(), - ! bind(&connector::GenericActiveInput::throttled, _1)) == inputs_.end()) + if (std::find_if(connectors().begin(), connectors().end(), + ! bind(&connector::GenericActiveInput::throttled, _1)) == connectors().end()) output.throttle(); } diff --git a/PPI/Joins.cti b/PPI/Joins.cti deleted file mode 100644 index 1e77d161f5a00ee80a5095fe56cb1673a5beb3b9..0000000000000000000000000000000000000000 --- a/PPI/Joins.cti +++ /dev/null @@ -1,91 +0,0 @@ -// $Id$ -// -// Copyright (C) 2007 -// Fraunhofer Institute for Open Communication Systems (FOKUS) -// Competence Center NETwork research (NET), St. Augustin, GERMANY -// Stefan Bund <g0dil@berlios.de> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the -// Free Software Foundation, Inc., -// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -/** \file - \brief Joins inline template implementation */ - -//#include "Joins.ih" - -// Custom includes -#include "Setup.hh" - -#define prefix_ inline -///////////////////////////////cti.p/////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////// -// senf::ppi::module::PassiveJoin - -template <class Source> -prefix_ senf::ppi::connector::GenericPassiveInput & -senf::ppi::module::PassiveJoin::connect(Source & source) -{ - connector::GenericPassiveInput & input (newInput()); - ppi::connect(source,input); - return input; -} - -/////////////////////////////////////////////////////////////////////////// -// senf::ppi::module::PriorityJoin - -template <class Source> -prefix_ senf::ppi::connector::GenericActiveInput & -senf::ppi::module::PriorityJoin::connect(Source & source, int priority) -{ - connector::GenericActiveInput & input (newInput(priority)); - ppi::connect(source,input); - return input; -} - -/////////////////////////////////////////////////////////////////////////// -// namespace members - -#ifndef DOXYGEN - -template <class Source> -prefix_ senf::ppi::connector::GenericPassiveInput & -senf::ppi::connect(Source & source, module::PassiveJoin & target) -{ - return target.connect(source); -} - -template <class Source> -prefix_ senf::ppi::connector::GenericActiveInput & -senf::ppi::connect(Source & source, module::PriorityJoin & target, int priority) -{ - return target.connect(source, priority); -} - -#endif - -///////////////////////////////cti.e/////////////////////////////////////// -#undef prefix_ - - -// Local Variables: -// mode: c++ -// fill-column: 100 -// comment-column: 40 -// c-file-style: "senf" -// indent-tabs-mode: nil -// ispell-local-dictionary: "american" -// compile-command: "scons -u test" -// End: diff --git a/PPI/Joins.hh b/PPI/Joins.hh index 8960551b24d73f12060f4259c621acf8f33c2119..a11ac41a65f2565b8c85570ac44421e1e62f5f20 100644 --- a/PPI/Joins.hh +++ b/PPI/Joins.hh @@ -31,6 +31,7 @@ #include "predecl.hh" #include "Connectors.hh" #include "Module.hh" +#include "DynamicConnectorMixin.hh" //#include "Joins.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -38,17 +39,6 @@ namespace senf { namespace ppi { -#ifndef DOXYGEN - - template <class Source> - connector::GenericPassiveInput & connect(Source & source, module::PassiveJoin & target); - - template <class Source> - connector::GenericActiveInput & connect(Source & source, module::PriorityJoin & target, - int priority = -1); - -#endif - namespace module { /** \brief Join multiple packet streams with passive inputs @@ -71,7 +61,8 @@ namespace module { \ingroup routing_modules */ class PassiveJoin - : public Module + : public Module, + public DynamicConnectorMixin<PassiveJoin, connector::PassiveInput<> > { SENF_PPI_MODULE(PassiveJoin); public: @@ -80,22 +71,12 @@ namespace module { PassiveJoin(); private: - connector::PassiveInput<> & newInput(); - -#ifndef DOXYGEN - // I didn't get template friend functions to work ... - public: -#endif - template <class Source> - connector::GenericPassiveInput & connect(Source & source); - - private: + void connectorSetup(connector::PassiveInput<> & conn); void request(connector::GenericPassiveInput & input); void onThrottle(); void onUnthrottle(); - typedef boost::ptr_vector<connector::PassiveInput<> > Inputs; - Inputs inputs_; + friend class DynamicConnectorMixin<PassiveJoin, connector::PassiveInput<> >; }; /** \brief Join multiple packet streams with active inputs @@ -125,7 +106,8 @@ namespace module { \ingroup routing_modules */ class PriorityJoin - : public Module + : public Module, + public DynamicConnectorMixin<PriorityJoin, connector::ActiveInput<> > { SENF_PPI_MODULE(PriorityJoin); public: @@ -134,21 +116,12 @@ namespace module { PriorityJoin(); private: - connector::ActiveInput<> & newInput(int priority); - -#ifndef DOXYGEN - public: -#endif - template <class Source> - connector::GenericActiveInput & connect(Source & source, int prioricty); - - private: + void connectorSetup(PriorityJoin::DynamicConnector & conn, int priority=-1); void request(); void onThrottle(); void onUnthrottle(); - typedef boost::ptr_vector<connector::ActiveInput<> > Inputs; - Inputs inputs_; + friend class DynamicConnectorMixin<PriorityJoin, connector::ActiveInput<> >; }; }}} @@ -156,7 +129,7 @@ namespace module { ///////////////////////////////hh.e//////////////////////////////////////// #include "Joins.cci" //#include "Joins.ct" -#include "Joins.cti" +//#include "Joins.cti" #endif diff --git a/PPI/Setup.cti b/PPI/Setup.cti index 509bbb112a8ea0099932262f9426841e68bc2044..ca6e672f5b40a70afd5aa6db2159f07972f2a62e 100644 --- a/PPI/Setup.cti +++ b/PPI/Setup.cti @@ -38,7 +38,7 @@ prefix_ void senf::ppi:: connect(T & source, C & target, typename boost::disable_if< boost::is_base_of<connector::Connector, T> >::type *, typename boost::enable_if< boost::is_base_of<connector::Connector, C> >::type *, - typename boost::disable_if< boost::is_base_of<connector::Jack, T> >::type *) + typename boost::disable_if< boost::is_base_of<detail::DisableStandardOutput, T> >::type *) { connect(source.output, target); } @@ -48,7 +48,7 @@ prefix_ void senf::ppi:: connect(C & source, T & target, typename boost::enable_if< boost::is_base_of<connector::Connector, C> >::type *, typename boost::disable_if< boost::is_base_of<connector::Connector,T> >::type *, - typename boost::disable_if< boost::is_base_of<connector::Jack, T> >::type *) + typename boost::disable_if< boost::is_base_of<detail::DisableStandardInput, T> >::type *) { connect(source, target.input); } @@ -58,8 +58,8 @@ prefix_ void senf::ppi:: connect(T1 & source, T2 & target, typename boost::disable_if< boost::is_base_of<connector::Connector, T1> >::type *, typename boost::disable_if< boost::is_base_of<connector::Connector, T2> >::type *, - typename boost::disable_if< boost::is_base_of<connector::Jack, T1> >::type *, - typename boost::disable_if< boost::is_base_of<connector::Jack, T2> >::type *) + typename boost::disable_if< boost::is_base_of<detail::DisableStandardOutput, T1> >:: type *, + typename boost::disable_if< boost::is_base_of<detail::DisableStandardInput, T2> >:: type *) { connect(source.output, target.input); } diff --git a/PPI/Setup.hh b/PPI/Setup.hh index 7ca50683275964384c53777cf74712ce8d871e1a..7b2c07abd92d0e797a49640aaa4cda080b93470a 100644 --- a/PPI/Setup.hh +++ b/PPI/Setup.hh @@ -37,6 +37,12 @@ namespace senf { namespace ppi { +namespace detail { + struct DisableStandardInput {}; + struct DisableStandardOutput {}; + struct DisableStandardConnect : public DisableStandardInput, public DisableStandardOutput {}; +} + #ifdef DOXYGEN /** \brief Connect modules @@ -77,20 +83,20 @@ namespace ppi { void connect(T & source, C & target, typename boost::disable_if< boost::is_base_of<connector::Connector, T> >::type * = 0, typename boost::enable_if< boost::is_base_of<connector::Connector, C> >::type * = 0, - typename boost::disable_if< boost::is_base_of<connector::Jack, T> >:: type * = 0); + typename boost::disable_if< boost::is_base_of<detail::DisableStandardOutput, T> >::type * = 0); template <class C, class T> void connect(C & source, T & target, typename boost::enable_if< boost::is_base_of<connector::Connector, C> >::type * = 0, typename boost::disable_if< boost::is_base_of<connector::Connector,T> >::type * = 0, - typename boost::disable_if< boost::is_base_of<connector::Jack, T> >:: type * = 0); + typename boost::disable_if< boost::is_base_of<detail::DisableStandardInput, T> >::type * = 0); template <class T1, class T2> void connect(T1 & source, T2 & target, typename boost::disable_if< boost::is_base_of<connector::Connector, T1> >::type * = 0, typename boost::disable_if< boost::is_base_of<connector::Connector, T2> >::type * = 0, - typename boost::disable_if< boost::is_base_of<connector::Jack, T1> >:: type * = 0, - typename boost::disable_if< boost::is_base_of<connector::Jack, T2> >:: type * = 0); + typename boost::disable_if< boost::is_base_of<detail::DisableStandardOutput, T1> >:: type * = 0, + typename boost::disable_if< boost::is_base_of<detail::DisableStandardInput, T2> >:: type * = 0); #endif diff --git a/PPI/predecl.hh b/PPI/predecl.hh index e5b1091badfe87b0db829992ac56b9360bc6a42e..0296cfd5eebae423341bf634993746d80859e8b4 100644 --- a/PPI/predecl.hh +++ b/PPI/predecl.hh @@ -61,6 +61,7 @@ namespace ppi { class BackwardForwardingRouteFromEventImplementation; template <class Source, class Target> class RouteImplementation; + struct DisableStandardConnect; } #endif