PPI: Implement DynamicConnectorMixin
g0dil [Fri, 26 Jun 2009 12:42:07 +0000 (12:42 +0000)]
PPI: Update all modules utilizing dynamic connectors to utilize the mixin

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1242 270642c3-0616-0410-b53a-bc976706d245

15 files changed:
PPI/AnnotationRouter.ct
PPI/AnnotationRouter.hh
PPI/Duplicators.cc
PPI/Duplicators.hh
PPI/DynamicConnectorMixin.cti [moved from PPI/Duplicators.cti with 64% similarity]
PPI/DynamicConnectorMixin.hh [new file with mode: 0644]
PPI/DynamicConnectorMixin.mpp [new file with mode: 0644]
PPI/DynamicConnectorMixin.test.cc [moved from PPI/AnnotationRouter.cti with 53% similarity]
PPI/Jack.hh
PPI/Joins.cc
PPI/Joins.cti [deleted file]
PPI/Joins.hh
PPI/Setup.cti
PPI/Setup.hh
PPI/predecl.hh

index bef2f9c..6231164 100644 (file)
@@ -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
index 705eb8d..7badaaf 100644 (file)
@@ -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
 
 \f
index f62679d..b6dd077 100644 (file)
 #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);
 }
index f5ea389..fea0a46 100644 (file)
 #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
 
 \f
similarity index 64%
rename from PPI/Duplicators.cti
rename to PPI/DynamicConnectorMixin.cti
index fb9e74f..97742b2 100644 (file)
 // 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 (file)
index 0000000..996dc05
--- /dev/null
@@ -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
+
+\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:
diff --git a/PPI/DynamicConnectorMixin.mpp b/PPI/DynamicConnectorMixin.mpp
new file mode 100644 (file)
index 0000000..19d6b8c
--- /dev/null
@@ -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////////////////////////////////////////
+
+\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:
similarity index 53%
rename from PPI/AnnotationRouter.cti
rename to PPI/DynamicConnectorMixin.test.cc
index d61468c..9eb5c3d 100644 (file)
@@ -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>
 // 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
index 52c6b82..a47d15d 100644 (file)
@@ -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 
index b8ce2d6..2ecccf3 100644 (file)
 ////////////////////////////////////////
 // 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 (file)
index 1e77d16..0000000
+++ /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_
-
-\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:
index 8960551..a11ac41 100644 (file)
@@ -31,6 +31,7 @@
 #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
@@ -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
 
 \f
index 509bbb1..ca6e672 100644 (file)
@@ -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);
 }
index 7ca5068..7b2c07a 100644 (file)
 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
     
index e5b1091..0296cfd 100644 (file)
@@ -61,6 +61,7 @@ namespace ppi {
         class BackwardForwardingRouteFromEventImplementation;
         template <class Source, class Target>
             class RouteImplementation;
+        struct DisableStandardConnect;
     }
 
 #endif