}
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
#include "../Utils/String.hh"
#include "Module.hh"
#include "Connectors.hh"
+#include "DynamicConnectorMixin.hh"
//#include "AnnotationRouter.mpp"
///////////////////////////////hh.p////////////////////////////////////////
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:
{ 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
\f
#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);
}
#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
\ingroup routing_modules
*/
class ActiveDuplicator
- : public Module
+ : public Module,
+ public DynamicConnectorMixin<ActiveDuplicator, connector::ActiveOutput<> >
{
SENF_PPI_MODULE(ActiveDuplicator);
public:
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<> >;
};
}}}
///////////////////////////////hh.e////////////////////////////////////////
#include "Duplicators.cci"
//#include "Duplicators.ct"
-#include "Duplicators.cti"
+//#include "Duplicators.cti"
#endif
\f
// 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_
--- /dev/null
+// $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
+
+\f
+// 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:
--- /dev/null
+// $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////////////////////////////////////////
+
+\f
+// 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:
// $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>
// 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_
\f
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
#include "Connectors.hh"
+#include "Setup.hh"
//#include "Jack.mpp"
///////////////////////////////hh.p////////////////////////////////////////
/** \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
////////////////////////////////////////
// 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)
{
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));
}
{
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));
}
////////////////////////////////////////
// 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();
}
+++ /dev/null
-// $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_
-
-\f
-// 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:
#include "predecl.hh"
#include "Connectors.hh"
#include "Module.hh"
+#include "DynamicConnectorMixin.hh"
//#include "Joins.mpp"
///////////////////////////////hh.p////////////////////////////////////////
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
\ingroup routing_modules
*/
class PassiveJoin
- : public Module
+ : public Module,
+ public DynamicConnectorMixin<PassiveJoin, connector::PassiveInput<> >
{
SENF_PPI_MODULE(PassiveJoin);
public:
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
\ingroup routing_modules
*/
class PriorityJoin
- : public Module
+ : public Module,
+ public DynamicConnectorMixin<PriorityJoin, connector::ActiveInput<> >
{
SENF_PPI_MODULE(PriorityJoin);
public:
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<> >;
};
}}}
///////////////////////////////hh.e////////////////////////////////////////
#include "Joins.cci"
//#include "Joins.ct"
-#include "Joins.cti"
+//#include "Joins.cti"
#endif
\f
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);
}
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);
}
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);
}
namespace senf {
namespace ppi {
+namespace detail {
+ struct DisableStandardInput {};
+ struct DisableStandardOutput {};
+ struct DisableStandardConnect : public DisableStandardInput, public DisableStandardOutput {};
+}
+
#ifdef DOXYGEN
/** \brief Connect modules
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
class BackwardForwardingRouteFromEventImplementation;
template <class Source, class Target>
class RouteImplementation;
+ struct DisableStandardConnect;
}
#endif