PPI: Implement DebugEvent
g0dil [Tue, 14 Aug 2007 14:30:29 +0000 (14:30 +0000)]
PPI: Fix PassivePackeSink: provide front() instead of back() members
PPI: Provide specializations for void-argument callbacks in Events and Route
PPI: Add notifyThrottle/notifyUnthrottle to EventDescriptor
PPI: Re-implement routing classes using a traits-based implementation
PPI: Add Route unit testing (mainly testing throttling)

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

19 files changed:
PPI/Connectors.hh
PPI/DebugEvent.cci [new file with mode: 0644]
PPI/DebugEvent.hh [new file with mode: 0644]
PPI/DebugModules.cci
PPI/DebugModules.hh
PPI/DebugModules.test.cc
PPI/EventManager.hh
PPI/Events.cci
PPI/Events.cti
PPI/Events.hh
PPI/Route.cci
PPI/Route.ct [new file with mode: 0644]
PPI/Route.cti
PPI/Route.hh
PPI/Route.ih
PPI/Route.test.cc
PPI/detail/EventBinding.cti
PPI/detail/EventBinding.hh
PPI/predecl.hh

index 6e01ca3..24b3bed 100644 (file)
@@ -150,8 +150,7 @@ namespace connector {
         bool remoteThrottled_;
         bool nativeThrottled_;
 
-        friend class senf::ppi::detail::ForwardForwardingRouteImplementation;
-        friend class senf::ppi::detail::BackwardForwardingRouteImplementation;
+        friend class senf::ppi::ForwardingRoute;
     };
 
     /** \brief Active connector baseclass
diff --git a/PPI/DebugEvent.cci b/PPI/DebugEvent.cci
new file mode 100644 (file)
index 0000000..df9bad5
--- /dev/null
@@ -0,0 +1,61 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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 DebugEvent inline non-template implementation */
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::DebugEvent
+
+prefix_ void senf::ppi::DebugEvent::trigger()
+{
+    if (enabled())
+        callback();
+}
+
+////////////////////////////////////////
+// private members
+
+prefix_ void senf::ppi::DebugEvent::v_enable()
+{}
+
+prefix_ void senf::ppi::DebugEvent::v_disable()
+{}
+
+///////////////////////////////cci.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:
diff --git a/PPI/DebugEvent.hh b/PPI/DebugEvent.hh
new file mode 100644 (file)
index 0000000..3a2f254
--- /dev/null
@@ -0,0 +1,86 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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 DebugEvent public header */
+
+#ifndef HH_DebugEvent_
+#define HH_DebugEvent_ 1
+
+// Custom includes
+#include "Events.hh"
+
+//#include "DebugEvent.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace ppi {
+
+    /** \brief
+      */
+    class DebugEvent
+        : public EventImplementation<>
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        // default default constructor
+        // default copy constructor
+        // default copy assignment
+        // default destructor
+        // no conversion constructors
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void trigger();
+
+    protected:
+
+    private:
+        virtual void v_enable();
+        virtual void v_disable();
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "DebugEvent.cci"
+//#include "DebugEvent.ct"
+//#include "DebugEvent.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:
index aa2a49e..58f367d 100644 (file)
@@ -129,19 +129,19 @@ senf::ppi::module::debug::PassivePacketSink::end()
     return packets_.end();
 }
 
-prefix_ senf::Packet senf::ppi::module::debug::PassivePacketSink::back()
+prefix_ senf::Packet senf::ppi::module::debug::PassivePacketSink::front()
 {
     if (empty())
         return Packet();
     else
-        return packets_.back();
+        return packets_.front();
 }
 
-prefix_ senf::Packet senf::ppi::module::debug::PassivePacketSink::pop_back()
+prefix_ senf::Packet senf::ppi::module::debug::PassivePacketSink::pop_front()
 {
-    Packet p (back());
+    Packet p (front());
     if (p) 
-        packets_.pop_back();
+        packets_.pop_front();
     return p;
 }
 
index 3ff2548..8730ad7 100644 (file)
@@ -103,8 +103,8 @@ namespace debug {
         iterator begin();
         iterator end();
 
-        Packet back();
-        Packet pop_back();
+        Packet front();
+        Packet pop_front();
 
         void clear();
 
index 3f19899..0fc70cc 100644 (file)
@@ -64,11 +64,11 @@ BOOST_AUTO_UNIT_TEST(debugModules)
             debug::PassivePacketSink::size_type(std::distance(sink.begin(),sink.end())),
             sink.size() );
         BOOST_CHECK( *sink.begin() == p );
-        BOOST_CHECK( sink.back() == p );
+        BOOST_CHECK( sink.front() == p );
 
         sink.clear();
 
-        BOOST_CHECK( ! sink.back() );
+        BOOST_CHECK( ! sink.front() );
         BOOST_CHECK( sink.empty() );
     }
 
index 46631e6..0c428ca 100644 (file)
@@ -55,7 +55,7 @@ namespace ppi {
         // struct is called 'Callback' and will hang in an endless loop somewhere
         struct Callback_
 #endif
-            : public detail::Callback<typename Descriptor::Event const &>
+            : public detail::Callback<typename Descriptor::EventArg>
         {};
 
         ///////////////////////////////////////////////////////////////////////////
index 8ffd90e..f511f40 100644 (file)
@@ -57,6 +57,20 @@ prefix_ senf::ppi::EventDescriptor::EventDescriptor()
     : enabled_(false)
 {}
 
+////////////////////////////////////////
+// private members
+
+prefix_ void senf::ppi::EventDescriptor::notifyThrottle()
+{
+    enabled(false);
+}
+
+prefix_ void senf::ppi::EventDescriptor::notifyUnthrottle()
+{
+    enabled(true);
+}
+
+
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index a7db87c..428e2cd 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::ppi::EventImplementation<EventType>
+// senf::ppi::EventImplementationHelper<EventType,Self>
 
 ////////////////////////////////////////
 // protected members
 
-template <class EventType>
-prefix_ senf::ppi::EventImplementation<EventType>::EventImplementation()
-    : binding_(0)
-{}
+template <class EventType, class Self>
+prefix_ void
+senf::ppi::EventImplementationHelper<EventType,Self>::callback(EventArg event,
+                                                               boost::posix_time::ptime time)
+{
+    binding().callback(event,time);
+}
 
-template <class EventType>
-prefix_ void senf::ppi::EventImplementation<EventType>::callback(EventArg event,
-                                                                 boost::posix_time::ptime time)
+template <class EventType, class Self>
+prefix_ void senf::ppi::EventImplementationHelper<EventType,Self>::callback(EventArg event)
 {
-    BOOST_ASSERT(binding_);
-    binding_->callback(event,time);
+    binding().callback(event);
 }
 
-template <class EventType>
-prefix_ void senf::ppi::EventImplementation<EventType>::callback(EventArg event)
+////////////////////////////////////////
+// private members
+
+template <class EventType, class Self>
+prefix_ senf::ppi::detail::EventBinding<EventType> &
+senf::ppi::EventImplementationHelper<EventType,Self>::binding()
+{
+    BOOST_ASSERT( static_cast<Self*>(this)->binding_ );
+    return * static_cast<Self*>(this)->binding_;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::EventImplementationHelper<void,Self>
+
+////////////////////////////////////////
+// protected members
+
+template <class Self>
+prefix_ void
+senf::ppi::EventImplementationHelper<void,Self>::callback(boost::posix_time::ptime time)
+{
+    binding().callback(time);
+}
+
+template <class Self>
+prefix_ void senf::ppi::EventImplementationHelper<void,Self>::callback()
 {
-    BOOST_ASSERT(binding_);
-    binding_->callback(event);
+    binding().callback();
 }
 
 ////////////////////////////////////////
 // private members
 
+template <class Self>
+prefix_ senf::ppi::detail::EventBinding<void> &
+senf::ppi::EventImplementationHelper<void,Self>::binding()
+{
+    BOOST_ASSERT( static_cast<Self*>(this)->binding_ );
+    return * static_cast<Self*>(this)->binding_;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::EventImplementation<EventType>
+
+////////////////////////////////////////
+// protected members
+
+template <class EventType>
+prefix_ senf::ppi::EventImplementation<EventType>::EventImplementation()
+    : binding_(0)
+{}
+
+////////////////////////////////////////
+// private members
+
 template <class EventType>
 prefix_ bool senf::ppi::EventImplementation<EventType>::v_isRegistered()
 {
index cb21dd7..fffd59e 100644 (file)
@@ -64,12 +64,42 @@ namespace ppi {
 
         virtual bool v_isRegistered() = 0;
 
+        void notifyThrottle();
+        void notifyUnthrottle();
+
         bool enabled_;
+
+        friend class ForwardingRoute;
+    };
+    
+    template <class EventType, class Self>
+    class EventImplementationHelper
+    {
+    protected:
+        typedef typename detail::EventArgType<EventType>::type EventArg;
+
+        void callback(EventArg event, boost::posix_time::ptime time);
+        void callback(EventArg event);
+
+    private:
+        detail::EventBinding<EventType> & binding();
+    };
+    
+    template <class Self>
+    class EventImplementationHelper<void,Self>
+    {
+    protected:
+        void callback(boost::posix_time::ptime time);
+        void callback();
+
+    private:
+        detail::EventBinding<void> & binding();
     };
 
     template <class EventType>
     class EventImplementation
-        : public EventDescriptor
+        : public EventDescriptor, 
+          public EventImplementationHelper< EventType, EventImplementation<EventType> >
     {
     public:
         typedef EventType Event;
@@ -78,9 +108,6 @@ namespace ppi {
     protected:
         EventImplementation();
 
-        void callback(EventArg event, boost::posix_time::ptime time);
-        void callback(EventArg event);
-
     private:
         virtual bool v_isRegistered();
         void setBinding(detail::EventBinding<Event> & binding);
@@ -88,6 +115,7 @@ namespace ppi {
         detail::EventBinding<Event> * binding_;
 
         friend class EventManager;
+        friend class EventImplementationHelper< EventType, EventImplementation<EventType> >;
     };
 
 }}
index 01c6f3a..f0e2279 100644 (file)
@@ -60,7 +60,7 @@ prefix_ void senf::ppi::ForwardingRoute::autoThrottling(bool state)
 // protected members
 
 prefix_ senf::ppi::ForwardingRoute::ForwardingRoute(module::Module & module)
-    : RouteBase(module), autoThrottling_(false)
+    : RouteBase(module), autoThrottling_(true)
 {}
 
 prefix_ void senf::ppi::ForwardingRoute::registerRoute(connector::ActiveConnector & connector)
@@ -81,164 +81,6 @@ prefix_ void senf::ppi::ForwardingRoute::notifyUnthrottle()
     v_notifyUnthrottle();
 }
 
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::NonForwardingRouteImplementation
-
-prefix_ senf::ppi::detail::NonForwardingRouteImplementation::
-NonForwardingRouteImplementation(module::Module & module, connector::InputConnector & source,
-                                 connector::OutputConnector & target)
-    : RouteBase(module), source_(&source), target_(&target)
-{}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::NonForwardingRouteToEventImplementation
-
-prefix_
-senf::ppi::detail::NonForwardingRouteToEventImplementation::
-NonForwardingRouteToEventImplementation(module::Module & module,
-                                        connector::InputConnector & source,
-                                        EventDescriptor & target)
-    : RouteBase(module), source_(&source), target_(&target)
-{}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::NonForwardingRouteFromEventImplementation
-
-prefix_
-senf::ppi::detail::NonForwardingRouteFromEventImplementation::
-NonForwardingRouteFromEventImplementation(module::Module & module, EventDescriptor & source,
-                                          connector::OutputConnector & target)
-    : RouteBase(module), source_(&source), target_(&target)
-{}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::ForwardForwardingRouteImplementation
-
-prefix_
-senf::ppi::detail::ForwardForwardingRouteImplementation::
-ForwardForwardingRouteImplementation(module::Module & module, connector::ActiveInput & source,
-                                     connector::PassiveOutput & target)
-    : ForwardingRoute(module), source_(&source), target_(&target)
-{
-    registerRoute(*source_);
-}
-
-prefix_ void senf::ppi::detail::ForwardForwardingRouteImplementation::v_notifyThrottle()
-{
-    if (autoThrottling())
-        target_->notifyThrottle();
-}
-
-prefix_ void senf::ppi::detail::ForwardForwardingRouteImplementation::v_notifyUnthrottle()
-{
-    if (autoThrottling())
-        target_->notifyUnthrottle();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::BackwardForwardingRouteImplementation
-
-prefix_
-senf::ppi::detail::BackwardForwardingRouteImplementation::
-BackwardForwardingRouteImplementation(module::Module & module,
-                                      connector::PassiveInput & source,
-                                      connector::ActiveOutput & target)
-    : ForwardingRoute(module), source_(&source), target_(&target)
-{
-    registerRoute(*target_);
-}
-
-prefix_ void senf::ppi::detail::BackwardForwardingRouteImplementation::v_notifyThrottle()
-{ 
-    if (autoThrottling())
-        source_->notifyThrottle();
-}
-
-prefix_ void senf::ppi::detail::BackwardForwardingRouteImplementation::v_notifyUnthrottle()
-{
-    if (autoThrottling())
-        source_->notifyUnthrottle();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::ForwardForwardingRouteToEventImplementation
-
-prefix_
-senf::ppi::detail::ForwardForwardingRouteToEventImplementation::
-ForwardForwardingRouteToEventImplementation(module::Module & module,
-                                            connector::ActiveInput & source,
-                                            EventDescriptor & target)
-    : ForwardingRoute(module), source_(&source), target_(&target)
-{
-    registerRoute(*source_);
-}
-
-prefix_ void senf::ppi::detail::ForwardForwardingRouteToEventImplementation::v_notifyThrottle()
-{
-    if (autoThrottling())
-        target_->enabled(false);
-}
-
-prefix_ void
-senf::ppi::detail::ForwardForwardingRouteToEventImplementation::v_notifyUnthrottle()
-{
-    if (autoThrottling())
-        target_->enabled(true);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//senf::ppi::detail::BackwardForwardingRouteFromEventImplementation
-
-prefix_
-senf::ppi::detail::BackwardForwardingRouteFromEventImplementation::
-BackwardForwardingRouteFromEventImplementation(module::Module & module,
-                                               EventDescriptor & source,
-                                               connector::ActiveOutput & target)
-    : ForwardingRoute(module), source_(&source), target_(&target)
-{
-    registerRoute(*target_);
-}
-
-prefix_ void
-senf::ppi::detail::BackwardForwardingRouteFromEventImplementation::v_notifyThrottle()
-{
-    if (autoThrottling())
-        source_->enabled(false);
-}
-
-prefix_ void
-senf::ppi::detail::BackwardForwardingRouteFromEventImplementation::v_notifyUnthrottle()
-{ 
-    if (autoThrottling())
-        source_->enabled(true);
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::RouteImplementation<connector::ActiveInput, connector::PassiveOutput, 
-//                                        false, false>
-
-prefix_
-senf::ppi::detail::RouteImplementation<senf::ppi::connector::ActiveInput, 
-                                       senf::ppi::connector::PassiveOutput, 
-                                       false, false>::
-RouteImplementation(module::Module & module, connector::ActiveInput & source,
-                    connector::PassiveOutput & target)
-    : ForwardForwardingRouteImplementation(module, source, target)
-{}
-
-////////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::RouteImplementation<connector::PassiveInput, connector::ActiveOutput, 
-//                                        false, false>
-
-prefix_
-senf::ppi::detail::RouteImplementation<senf::ppi::connector::PassiveInput, 
-                                       senf::ppi::connector::ActiveOutput, 
-                                       false, false>::
-RouteImplementation(module::Module & module, connector::PassiveInput & source,
-                    connector::ActiveOutput & target)
-    : BackwardForwardingRouteImplementation(module, source, target)
-{}
-
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
diff --git a/PPI/Route.ct b/PPI/Route.ct
new file mode 100644 (file)
index 0000000..fb1cc0c
--- /dev/null
@@ -0,0 +1,70 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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 Route non-inline template implementation  */
+
+#include "Route.ih"
+
+// Custom includes
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::detail::ForwardingRouteImplementation<Source,Target>
+
+////////////////////////////////////////
+// private members
+
+template <class Source, class Target>
+prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::v_notifyThrottle()
+{
+    if (this->autoThrottling()) {
+        notifyThrottle(this->source(),boost::mpl::bool_<RoutingTraits<Source>::notifyTarget>());
+        notifyThrottle(this->target(),boost::mpl::bool_<RoutingTraits<Target>::notifyTarget>());
+    }
+}
+
+template <class Source, class Target>
+prefix_ void
+senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::v_notifyUnthrottle()
+{
+    if (this->autoThrottling()) {
+        notifyUnthrottle(this->source(),boost::mpl::bool_<RoutingTraits<Source>::notifyTarget>());
+        notifyUnthrottle(this->target(),boost::mpl::bool_<RoutingTraits<Target>::notifyTarget>());
+    }
+}
+
+///////////////////////////////ct.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 015ea90..a136aff 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::RouteImplementation<Source,Target,srcEvent,trgEvent>
+// senf::ppi::Route<Source,Target>
 
-template <class Source, class Target, bool srcEvent, bool trgEvent>
-prefix_
-senf::ppi::detail::RouteImplementation<Source,Target,srcEvent,trgEvent>::
-RouteImplementation(module::Module & module, Source & source, Target & target)
-    : NonForwardingRouteImplementation(module, source, target)
+template <class Source, class Target>
+prefix_ senf::ppi::Route<Source,Target>::Route(module::Module & module, Source & source,
+                                               Target & target)
+    : Base(module,source,target)
 {}
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::RouteImplementation<Source, Target, true, false>
+// senf::ppi::ForwardingRoute
 
-template <class Source, class Target>
-prefix_
-senf::ppi::detail::RouteImplementation<Source, Target, true, false>::
-RouteImplementation(module::Module & module, Source & source, Target & target)
-    : NonForwardingRouteFromEventImplementation(module, source, target)
+////////////////////////////////////////
+// protected members
+
+template <class T>
+prefix_ void senf::ppi::ForwardingRoute::notifyThrottle(T & ob)
+{
+    ob.notifyThrottle();
+}
+
+template <class T>
+prefix_ void senf::ppi::ForwardingRoute::notifyUnthrottle(T & ob)
+{
+    ob.notifyUnthrottle();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>
+
+template <class Source, class Target, class Base>
+prefix_ Source & senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::source()
+{
+    return *source_;
+}
+
+template <class Source, class Target, class Base>
+prefix_ Target & senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::target()
+{
+    return *target_;
+}
+
+////////////////////////////////////////
+// protected members
+
+template <class Source, class Target, class Base>
+prefix_ senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::
+BaseRouteImplementation(module::Module & module, Source & source, Target & target)
+    : Base(module), source_(&source), target_(&target)
 {}
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::RouteImplementation<Source, Target, false, true>
+// senf::ppi::detail::ForwardingRouteImplementation<Source,Target>
+
+////////////////////////////////////////
+// protected members
 
 template <class Source, class Target>
 prefix_
-senf::ppi::detail::RouteImplementation<Source, Target, false, true>::
-RouteImplementation(module::Module & module, Source & source, Target & target)
-    : NonForwardingRouteToEventImplementation(module, source, target)
+senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+ForwardingRouteImplementation(module::Module & module, Source & source, Target & target)
+    : Base(module,source,target)
+{
+    registerRoute(source, boost::mpl::bool_<RoutingTraits<Source>::notifySource>());
+    registerRoute(target, boost::mpl::bool_<RoutingTraits<Target>::notifySource>());
+}
+
+////////////////////////////////////////
+// private members
+
+template <class Source, class Target>
+template <class T>
+prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+registerRoute(T & ob, boost::mpl::bool_<true> const &)
+{
+    ForwardingRoute::registerRoute(ob);
+}
+
+template <class Source, class Target>
+template <class T>
+prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+registerRoute(T & ob, boost::mpl::bool_<false> const &)
 {}
 
-///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::RouteImplementation<connector::ActiveInput, Event, false, true>
+template <class Source, class Target>
+template <class T>
+prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+notifyThrottle(T & ob, boost::mpl::bool_<true> const &)
+{
+    ForwardingRoute::notifyThrottle(ob);
+}
 
-template <class Event>
-prefix_
-senf::ppi::detail::RouteImplementation<senf::ppi::connector::ActiveInput, Event, false, true>::
-RouteImplementation(module::Module & module, connector::ActiveInput & source, Event & target)
-    : ForwardForwardingRouteToEventImplementation(module, source, target)
+template <class Source, class Target>
+template <class T>
+prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+notifyThrottle(T & ob, boost::mpl::bool_<false> const &)
+{}
+
+template <class Source, class Target>
+template <class T>
+prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+notifyUnthrottle(T & ob, boost::mpl::bool_<true> const &)
+{
+    ForwardingRoute::notifyUnthrottle(ob);
+}
+
+template <class Source, class Target>
+template <class T>
+prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+notifyUnthrottle(T & ob, boost::mpl::bool_<false> const &)
 {}
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::ppi::detail::RouteImplementation<Event, connector::ActiveOutput, true, false>
+// senf::ppi::detail::RouteImplementation2<Source,Target>
 
-template <class Event>
-prefix_
-senf::ppi::detail::RouteImplementation<Event, senf::ppi::connector::ActiveOutput, true, false>::
-RouteImplementation(module::Module & module, Event & source, connector::ActiveOutput & target)
-    : BackwardForwardingRouteFromEventImplementation(module, source, target)
+////////////////////////////////////////
+// protected members
+
+template <class Source, class Target>
+prefix_ senf::ppi::detail::RouteImplementation2<Source,Target>::
+RouteImplementation2(module::Module & module, Source & source, Target & target)
+    : Base(module,source,target)
 {}
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::ppi::Route<Source,Target>
+// senf::ppi::detail::RouteImplementation<Source,Target>
 
 ////////////////////////////////////////
 // protected members
 
 template <class Source, class Target>
-prefix_ senf::ppi::Route<Source,Target>::Route(module::Module & module, Source & source,
-                                               Target & target)
-    : Implementation(module, source, target)
+prefix_ senf::ppi::detail::RouteImplementation<Source,Target>::
+RouteImplementation(module::Module & module, Source & source, Target & target)
+    : Base(module,source,target)
 {}
 
 ///////////////////////////////cti.e///////////////////////////////////////
index e3eee1c..f765152 100644 (file)
@@ -72,6 +72,9 @@ namespace ppi {
         // Called to register this route with the connectors forwarding information base
         void registerRoute(connector::ActiveConnector & connector);
 
+        template <class T> void notifyThrottle(T & ob);
+        template <class T> void notifyUnthrottle(T & ob);
+
     private:
         // called to forward a throttling notification along the route
         void notifyThrottle();
@@ -103,6 +106,7 @@ namespace ppi {
     class Route
         : public detail::RouteImplementation<Source,Target>
     {
+        typedef detail::RouteImplementation<Source,Target> Base;
     private:
         typedef detail::RouteImplementation<Source,Target> Implementation;
         
@@ -115,7 +119,7 @@ namespace ppi {
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "Route.cci"
-//#include "Route.ct"
+#include "Route.ct"
 #include "Route.cti"
 #endif
 
index 1e76429..149b9e9 100644 (file)
 #define IH_Route_ 1
 
 // Custom includes
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/static_assert.hpp>
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
@@ -34,185 +39,164 @@ namespace senf {
 namespace ppi {
 namespace detail {
 
-    // Valid Forwarding routes:
-    //   Forward throttling
-    //     ActiveInput -> PassiveOutput
-    //       tempalte<> RouteImplementation<ActiveInput,PassiveOutput,false,false>
-    //     ActiveInput -> Event
-    //       template<class Event> class RouteImplementation<ActiveInput, Event, false, true>
-    //   Backward throttling
-    //     PassiveInput -> ActiveOutput
-    //       template<> RouteImplementation<PassiveInput, ActiveOutput, false, false>
-    //     Event -> ActiveOutput
-    //       template<class Event> class RouteImplementation<Event, ActiveOutput, true, false>
-
-    class NonForwardingRouteImplementation
-        : public RouteBase
+    // This is the RoutingTraits implementation for Connectors. Events are handled in the
+    // specialization below
+    template <class Connector, bool isEvent>
+    struct RoutingTraitsImplementation
     {
-    protected:
-        NonForwardingRouteImplementation(module::Module & module, 
-                                         connector::InputConnector & source,
-                                         connector::OutputConnector & target);
+        BOOST_STATIC_ASSERT((boost::is_base_of<connector::Connector, Connector>::value));
 
-    private:
-        connector::InputConnector * source_;
-        connector::OutputConnector * target_;
-    };
+        static bool const notifySource = boost::is_base_of<
+            connector::ActiveConnector, Connector>::value;
+        static bool const notifyTarget = boost::is_base_of<
+            connector::PassiveConnector, Connector>::value;
 
-    class NonForwardingRouteToEventImplementation
-        : public RouteBase
-    {
-    protected:
-        NonForwardingRouteToEventImplementation(module::Module & module,
-                                                connector::InputConnector & source,
-                                                EventDescriptor & target);
+        static bool const dataSource = boost::is_base_of<
+            connector::InputConnector, Connector>::value;
+        static bool const dataTarget = boost::is_base_of<
+            connector::OutputConnector, Connector>::value;
         
-    private:
-        connector::InputConnector * source_;
-        EventDescriptor * target_;
+        typedef Connector type;
     };
 
-    class NonForwardingRouteFromEventImplementation
-        : public RouteBase
+    // RoutingTraits specialization for Event types. Events may be both dataSource or dataTarget but
+    // cannot be notifySource.
+    template <class Event>
+    struct RoutingTraitsImplementation<Event,true>
     {
-    protected:
-        NonForwardingRouteFromEventImplementation(module::Module & module,
-                                                  EventDescriptor & source,
-                                                  connector::OutputConnector & target);
+        static bool const notifySource = false;
+        static bool const notifyTarget = true;
 
-    private:
-        EventDescriptor * source_;
-        connector::OutputConnector * target_;
-    };
+        static bool const dataSource = true;
+        static bool const dataTarget = true;
 
-    class ForwardForwardingRouteImplementation
-        : public ForwardingRoute
+        typedef EventDescriptor type;
+    };
+    
+    // The RoutingTraits give routing related information about the argument type:
+    //  - Wether the type is a notifySource or notifyTarget
+    //  - Wether the type is dataSource or dataTarget
+    //  - Provide the generalized target type
+    //
+    // The real implementation is in RoutingTraitsImplementation which is appropriately specialized
+    // for Events
+    template <class Object>
+    struct RoutingTraits
+        : public RoutingTraitsImplementation<Object, 
+                                             boost::is_convertible<Object*,
+                                                                   EventDescriptor*>::value>
+    {};
+
+    // This is the generic route implementation for all routes. It just provides access to the 
+    // source and target.
+    template <class Source, class Target, class Base>
+    class BaseRouteImplementation
+        : public Base
     {
-    protected:
-        ForwardForwardingRouteImplementation(module::Module & module,
-                                             connector::ActiveInput & source,
-                                             connector::PassiveOutput & target);
-
-    private:
-        virtual void v_notifyThrottle();
-        virtual void v_notifyUnthrottle();
+    public:
+        typedef Source source_type;
+        typedef Target target_type;
 
-        connector::ActiveInput * source_;
-        connector::PassiveOutput * target_;
-    };
+        Source & source();
+        Target & target();
 
-    class BackwardForwardingRouteImplementation
-        : public ForwardingRoute
-    {
     protected:
-        BackwardForwardingRouteImplementation(module::Module & module,
-                                              connector::PassiveInput & source,
-                                              connector::ActiveOutput & target);
+        BaseRouteImplementation(module::Module & module, Source & source, Target & target);
 
     private:
-        virtual void v_notifyThrottle();
-        virtual void v_notifyUnthrottle();
-        
-        connector::PassiveInput * source_;
-        connector::ActiveOutput * target_;
+        Source * source_;
+        Target * target_;
     };
 
-    class ForwardForwardingRouteToEventImplementation
-        : public ForwardingRoute
+    // The ForwardingRouteImplementation is based on the same BaseRouteImplementation
+    // as non-forwarding routes are but injects a different base-class (the third template
+    // argument to BaseRouteImplementation). ForwardingRouteImplementation has two additional
+    // functions:
+    //  1) Register the ForwardingRoute with the notifySource
+    //  2) Implement the abstract ForwardingRoute interface
+    //
+    // Since we don't know explicitly, which of Source or Target is the notifySource or
+    // notifyTarget, the implementation calls registerRoute and notifyThrottle/notifyUnthrottle on
+    // *both*, the source and target, however qualified with an additional argument of type
+    // boost::mpl::bool_ which is used to select the correct overloads, of which the 'false'
+    // overload always is a no-op. This way, only the correct call will generate any code, the
+    // disabled call will be optimized away.
+    template <class Source, class Target>
+    class ForwardingRouteImplementation
+        : public BaseRouteImplementation<Source, Target, ForwardingRoute>
     {
+        typedef BaseRouteImplementation<Source, Target, ForwardingRoute> Base;
+        
     protected:
-        ForwardForwardingRouteToEventImplementation(module::Module & module,
-                                                    connector::ActiveInput & source,
-                                                    EventDescriptor & target);
+        ForwardingRouteImplementation(module::Module & module, Source & source, Target & target);
 
     private:
-        virtual void v_notifyThrottle();
-        virtual void v_notifyUnthrottle();
+        // register the Route in the notifySource only if the second argument is a 'true' type
+        template <class T> void registerRoute(T & ob, boost::mpl::bool_<true> const &);
+        template <class T> void registerRoute(T & ob, boost::mpl::bool_<false> const &);
 
-        connector::ActiveInput * source_;
-        EventDescriptor * target_;
-    };
-
-    class BackwardForwardingRouteFromEventImplementation
-        : public ForwardingRoute
-    {
-    protected:
-        BackwardForwardingRouteFromEventImplementation(module::Module & module,
-                                                       EventDescriptor & source,
-                                                       connector::ActiveOutput & target); 
+        // send a throttle/unthrottle notification  only if the second argument is a 'true' type
+        template <class T> void notifyThrottle(T & ob, boost::mpl::bool_<true> const &);
+        template <class T> void notifyThrottle(T & ob, boost::mpl::bool_<false> const &);
+        template <class T> void notifyUnthrottle(T & ob, boost::mpl::bool_<true> const &);
+        template <class T> void notifyUnthrottle(T & ob, boost::mpl::bool_<false> const &);
 
-    private:
         virtual void v_notifyThrottle();
         virtual void v_notifyUnthrottle();
-
-        EventDescriptor * source_;
-        connector::ActiveOutput * target_;
     };
 
-    template <class Source, class Target, bool srcEvent, bool trgEvent>
-    class RouteImplementation
-        : public NonForwardingRouteImplementation
+    // This helper class finds the base-class suitable for a specific route. Routes are classified
+    // into two groups: 
+    //  1) A forwarding routes is a routed which forwards notifications from a notifySource to a
+    //     notifyTarget. Forwarding routes are implemneted using ForwardingRouteImplementation
+    //  2) Non-forwarding routes don't forward notifications. They are implemented directly
+    //     using BaseRouteImplementation
+    template <class Source, class Target>
+    struct RouteImplementationBase
     {
-    protected:
-        RouteImplementation(module::Module & module, Source & source, Target & target);
-    };
+        typedef RoutingTraits<Source> srcTrait;
+        typedef RoutingTraits<Target> trgTrait;
 
-#   ifndef DOXYGEN
+        static bool const isForwarding = (srcTrait::notifySource && trgTrait::notifyTarget)
+            || (srcTrait::notifyTarget && trgTrait::notifySource);
+        
+        typedef typename boost::mpl::if_c<
+            isForwarding, 
+            ForwardingRouteImplementation<Source,Target>, 
+            BaseRouteImplementation<Source,Target,RouteBase> >::type base;
+    };
 
+    // RouteImplementation2 has two purposes: 
+    //  1) Ensure, that routing is always from a data source to a data target
+    //  2) To find the correct base-class. This is delegated to RouteImplementationBase
     template <class Source, class Target>
-    class RouteImplementation<Source, Target, true, false>
-        : public NonForwardingRouteFromEventImplementation
+    class RouteImplementation2
+        : public RouteImplementationBase<Source,Target>::base
     {
-    protected:
-        RouteImplementation(module::Module & module, Source & source, Target & target);
-    };
+        typedef typename RouteImplementationBase<Source,Target>::base Base;
 
-    template<class Source, class Target>
-    class RouteImplementation<Source, Target, false, true>
-        : public NonForwardingRouteToEventImplementation
-    {
-    protected:
-        RouteImplementation(module::Module & module, Source & source, Target & target);
-    };
+        BOOST_STATIC_ASSERT( RoutingTraits<Source>::dataSource && 
+                             RoutingTraits<Target>::dataTarget );
 
-    template<>
-    class RouteImplementation<connector::ActiveInput, connector::PassiveOutput, false, false>
-        : public ForwardForwardingRouteImplementation
-    {
     protected:
-        RouteImplementation(module::Module & module, connector::ActiveInput & source, 
-                            connector::PassiveOutput & target);
+        RouteImplementation2(module::Module & module, Source & source, Target & target);
     };
 
-    template <class Event>
-    class RouteImplementation<connector::ActiveInput, Event, false, true>
-        : public ForwardForwardingRouteToEventImplementation
+    // RouteImplementation just forwards to RouteImplementation2 replacing the template arguments
+    // with the appropriately generalized type: If either Source or Target is an Event type, it is
+    // replaced with the general Event base-class EventDescriptor. Connector types are left as is.
+    template <class Source, class Target>
+    class RouteImplementation
+        : public RouteImplementation2<typename RoutingTraits<Source>::type,
+                                      typename RoutingTraits<Target>::type>
     {
-    protected:
-        RouteImplementation(module::Module & module, connector::ActiveInput & source, 
-                            Event & target);
-    };
+        typedef RouteImplementation2<typename RoutingTraits<Source>::type,
+                                     typename RoutingTraits<Target>::type> Base;
 
-    template <>
-    class RouteImplementation<connector::PassiveInput, connector::ActiveOutput, false, false>
-        : public BackwardForwardingRouteImplementation
-    {
     protected:
-        RouteImplementation(module::Module & module, connector::PassiveInput & source, 
-                            connector::ActiveOutput & target);
-    };
-    
-    template <class Event>
-    class RouteImplementation<Event, connector::ActiveOutput, true, false>
-        : public BackwardForwardingRouteFromEventImplementation
-    {
-    protected:
-        RouteImplementation(module::Module & module, Event & source, 
-                            connector::ActiveOutput & target);
+        RouteImplementation(module::Module & module, Source & source, Target & target);
     };
 
-#   endif
-
 }}}
 
 ///////////////////////////////ih.e////////////////////////////////////////
index 2337e9e..45b45ca 100644 (file)
 
 // Custom includes
 #include "Route.hh"
+#include "DebugEvent.hh"
+#include "DebugModules.hh"
+#include "Module.hh"
+#include "Setup.hh"
 
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/test_tools.hpp>
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
+namespace ppi = senf::ppi;
+namespace connector = ppi::connector;
+namespace module = ppi::module;
+namespace debug = module::debug;
+
+namespace {
+    class RouteTester : public module::Module
+    {
+    public:
+        connector::ActiveInput activeIn;
+        connector::PassiveInput passiveIn;
+
+        connector::ActiveOutput activeOut;
+        connector::PassiveOutput passiveOut;
+
+        ppi::DebugEvent event;
+
+        ppi::ForwardingRoute * rt;
+        
+        RouteTester() : events(0), throttles(0) {
+                   route( activeIn,  activeOut  );  // non-forwarding
+            rt = & route( activeIn,  passiveOut );  // forward throttling
+                   route( passiveIn, activeOut  );  // backward throttling
+                   route( passiveIn, passiveOut );  // non-forwarding
+                   route( event,     activeOut  );  // forward event throttling
+                   route( activeIn,  event      );  // backward event throttling
+
+            passiveIn.onRequest(&RouteTester::inputRequest);
+            passiveOut.onRequest(&RouteTester::outputRequest);
+            registerEvent(&RouteTester::onEvent, event);
+
+            activeIn.onThrottle(&RouteTester::throttleRequest);
+            activeIn.onUnthrottle(&RouteTester::unthrottleRequest);
+            activeOut.onThrottle(&RouteTester::throttleRequest);
+            activeOut.onUnthrottle(&RouteTester::unthrottleRequest);
+        }
+
+        void inputRequest() {
+            activeOut(passiveIn());
+        }
+
+        void outputRequest() {
+            passiveOut(activeIn());
+        }
+
+        void onEvent() {
+            ++ events;
+        }
+
+        void throttleRequest() {
+            ++ throttles;
+        }
+        
+        void unthrottleRequest() {
+            -- throttles;
+        }
+
+        unsigned events;
+        int throttles;
+    };
+}
+
 BOOST_AUTO_UNIT_TEST(route)
-{}
+{
+    debug::PassivePacketSource passiveSource;
+    debug::ActivePacketSource activeSource;
+    debug::PassivePacketSink passiveSink;
+    debug::ActivePacketSink activeSink;
+    RouteTester tester;
+
+    ppi::connect(passiveSource.output, tester.activeIn);
+    ppi::connect(activeSource.output, tester.passiveIn);
+    ppi::connect(tester.activeOut, passiveSink.input);
+    ppi::connect(tester.passiveOut, activeSink.input);
+
+    ppi::init();
+
+    senf::Packet p1 (senf::DataPacket::create());
+    senf::Packet p2 (senf::DataPacket::create());
+
+    passiveSource.submit(p1);
+    activeSource.submit(p2);
+
+    BOOST_CHECK( p2 == passiveSink.front() );
+
+    // The passive source is not throttled at this point since it has packets in queue
+
+    passiveSink.input.throttle();
+    BOOST_CHECK( passiveSink.input.throttled() );
+    BOOST_CHECK( ! tester.activeOut );
+    BOOST_CHECK_EQUAL( tester.throttles, 1 );
+    BOOST_CHECK( tester.passiveIn.throttled() );
+    BOOST_CHECK( ! activeSource.output );
+    BOOST_CHECK( ! tester.event.enabled() );
+
+    passiveSink.input.unthrottle();
+    BOOST_CHECK( activeSource.output );
+    BOOST_CHECK( tester.event.enabled() );
+    
+
+    // Now throttle the passive source by exhausting the queue
+    
+    BOOST_CHECK( p1 == activeSink.request() );
+    BOOST_CHECK( passiveSource.output.throttled() );
+    BOOST_CHECK( ! tester.activeIn );
+    BOOST_CHECK_EQUAL( tester.throttles, 1 );
+    BOOST_CHECK( tester.passiveOut.throttled() );
+    BOOST_CHECK( ! activeSink.input );
+    BOOST_CHECK( ! tester.event.enabled() );
+    
+    passiveSource.submit(p1);
+    BOOST_CHECK( activeSink.input );
+    BOOST_CHECK( tester.event.enabled() );
+
+    tester.rt->autoThrottling(false);
+
+    BOOST_CHECK( p1 == activeSink.request() );
+    BOOST_CHECK( passiveSource.output.throttled() );
+    BOOST_CHECK( activeSink.input );
+}
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
index aeb0555..f37637e 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
+// senf::ppi::detail::EventBindingHelper<EventType,Self>
+
+template <class EventType, class Self>
+prefix_ void
+senf::ppi::detail::EventBindingHelper<EventType,Self>::callback(EventArg event,
+                                                                boost::posix_time::ptime time)
+{
+    self().eventTime(time);
+    self().callback_(event);
+}
+
+template <class EventType, class Self>
+prefix_ void senf::ppi::detail::EventBindingHelper<EventType,Self>::callback(EventArg event)
+{
+    callback(event, boost::posix_time::microsec_clock::universal_time());
+}
+
+////////////////////////////////////////
+// private members
+
+template <class EventType, class Self>
+prefix_ Self & senf::ppi::detail::EventBindingHelper<EventType,Self>::self()
+{
+    return * static_cast<Self*>(this);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::detail::EventBindingHelper<void,Self>
+
+template <class Self>
+prefix_ void
+senf::ppi::detail::EventBindingHelper<void,Self>::callback(boost::posix_time::ptime time)
+{
+    self().eventTime(time);
+    self().callback_();
+}
+
+template <class Self>
+prefix_ void senf::ppi::detail::EventBindingHelper<void,Self>::callback()
+{
+    callback(boost::posix_time::microsec_clock::universal_time());
+}
+
+////////////////////////////////////////
+// private members
+
+template <class Self>
+prefix_ Self & senf::ppi::detail::EventBindingHelper<void,Self>::self()
+{
+    return * static_cast<Self*>(this);
+}
+
+///////////////////////////////////////////////////////////////////////////
 // senf::ppi::detail::EventBinding<EvImpl>
 
 template <class EventType>
@@ -41,20 +94,6 @@ prefix_ senf::ppi::detail::EventBinding<EventType>::EventBinding(EventManager &
     : EventBindingBase(manager, module, descriptor), callback_(callback)
 {}
 
-template <class EvImpl>
-prefix_ void senf::ppi::detail::EventBinding<EvImpl>::callback(EventArg event,
-                                                               boost::posix_time::ptime time)
-{
-    eventTime(time);
-    callback_(event);
-}
-
-template <class EvImpl>
-prefix_ void senf::ppi::detail::EventBinding<EvImpl>::callback(EventArg event)
-{
-    callback(event, boost::posix_time::microsec_clock::universal_time());
-}
-
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 10959d7..addda33 100644 (file)
@@ -52,23 +52,47 @@ namespace detail {
         EventDescriptor * descriptor_;
     };
 
+    template <class EventType, class Self>
+    class EventBindingHelper
+    {
+    public:
+        typedef typename detail::EventArgType<EventType>::type EventArg;
+
+        void callback(EventArg event, boost::posix_time::ptime time);
+        void callback(EventArg event);
+        
+    private:
+        Self & self();
+    };
+
+    template <class Self>
+    class EventBindingHelper<void,Self>
+    {
+    public:
+        void callback(boost::posix_time::ptime time);
+        void callback();
+        
+    private:
+        Self & self();
+    };
+
     template <class EventType>
     class EventBinding
-        : public EventBindingBase
+        : public EventBindingBase, 
+          public EventBindingHelper<EventType, EventBinding<EventType> >
     {
     public:
         typedef EventType Event;
         typedef typename detail::EventArgType<Event>::type EventArg;
-        typedef typename detail::Callback<Event const &>::type Callback;
+        typedef typename detail::Callback<EventArg>::type Callback;
 
         EventBinding(EventManager & manager, module::Module & module, Callback callback,
                      EventDescriptor & descriptor);
 
-        void callback(EventArg event, boost::posix_time::ptime time);
-        void callback(EventArg event);
-
     private:
         Callback callback_;
+
+        friend class EventBindingHelper<EventType, EventBinding<EventType> >;
     };
 
 }}}
index be9c053..2b8f6ea 100644 (file)
@@ -55,9 +55,7 @@ namespace ppi {
         class BackwardForwardingRouteImplementation;
         class ForwardForwardingRouteToEventImplementation;
         class BackwardForwardingRouteFromEventImplementation;
-        template <class Source, class Target, 
-                  bool srcEvent = boost::is_base_of<EventDescriptor,Source>::value,
-                  bool trgEvent = boost::is_base_of<EventDescriptor,Target>::value>
+        template <class Source, class Target>
             class RouteImplementation;
     }