PPI: Add support for multiple notify sources per notify target
g0dil [Thu, 16 Aug 2007 11:22:14 +0000 (11:22 +0000)]
PPI: Add boolean test for debug modules

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

14 files changed:
PPI/Connectors.cc
PPI/Connectors.cci
PPI/Connectors.hh
PPI/DebugModules.cci
PPI/DebugModules.hh
PPI/Events.cc [new file with mode: 0644]
PPI/Events.cci
PPI/Events.hh
PPI/Route.cci
PPI/Route.ct
PPI/Route.cti
PPI/Route.hh
PPI/Route.ih
PPI/Route.test.cc

index 7fe75a0..058a85c 100644 (file)
 ////////////////////////////////////////
 // private members
 
+prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle()
+{
+    if (throttled() && !nativeThrottled_) {
+        Routes::const_iterator i (routes_.begin());
+        Routes::const_iterator const i_end (routes_.end());
+        for (; i != i_end; ++i)
+            if ((*i)->throttled())
+                break;
+        if (i == i_end) {
+            remoteThrottled_ = false;
+            emitUnthrottle();
+        }
+    } 
+    else
+        remoteThrottled_ = false;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::connector::ActiveConnector
 
index 3862aab..a046feb 100644 (file)
@@ -134,16 +134,6 @@ prefix_ void senf::ppi::connector::PassiveConnector::notifyThrottle()
         remoteThrottled_ = true;
 }
 
-prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle()
-{
-    if (throttled() && !nativeThrottled_) {
-        remoteThrottled_ = false;
-        emitUnthrottle();
-    } 
-    else
-        remoteThrottled_ = false;
-}
-
 prefix_ void senf::ppi::connector::PassiveConnector::emitThrottle()
 {
     peer().notifyThrottle();
@@ -158,6 +148,11 @@ prefix_ void senf::ppi::connector::PassiveConnector::emitUnthrottle()
 prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent()
 {}
 
+prefix_ void senf::ppi::connector::PassiveConnector::registerRoute(ForwardingRoute & route)
+{
+    routes_.push_back(&route);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::connector::ActiveConnector
 
@@ -177,6 +172,12 @@ prefix_ void senf::ppi::connector::ActiveConnector::onUnthrottle()
     unthrottleCallback_ = Callback();
 }
 
+prefix_ bool senf::ppi::connector::ActiveConnector::throttled()
+    const
+{
+    return peer().throttled();
+}
+
 ////////////////////////////////////////
 // protected members
 
index 24b3bed..6d47b63 100644 (file)
@@ -144,12 +144,18 @@ namespace connector {
         // Called after unthrottling the connector
         virtual void v_unthrottleEvent();
 
+        // called by ForwardingRoute to register a new route
+        void registerRoute(ForwardingRoute & route);
+
         typedef detail::Callback<>::type Callback;
         Callback callback_;
 
         bool remoteThrottled_;
         bool nativeThrottled_;
 
+        typedef std::vector<ForwardingRoute*> Routes;
+        Routes routes_;
+
         friend class senf::ppi::ForwardingRoute;
     };
 
@@ -194,6 +200,8 @@ namespace connector {
                                                  notifications. */
         void onUnthrottle();
 
+        bool throttled() const;
+
         PassiveConnector & peer() const;
 
     protected:
index 58f367d..278aac3 100644 (file)
@@ -41,6 +41,12 @@ prefix_ void senf::ppi::module::debug::ActivePacketSource::submit(Packet packet)
     output(packet);
 }
 
+prefix_ bool senf::ppi::module::debug::ActivePacketSource::boolean_test()
+    const
+{
+    return output;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::module::debug::PassivePacketSource
 
@@ -97,6 +103,12 @@ prefix_ senf::Packet senf::ppi::module::debug::ActivePacketSink::request()
     return input();
 }
 
+prefix_ bool senf::ppi::module::debug::ActivePacketSink::boolean_test()
+    const
+{
+    return input;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::module::debug::PassivePacketSink
 
index 8730ad7..1a38d4b 100644 (file)
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include <deque>
+#include "Utils/SafeBool.hh"
 #include "Packets/Packets.hh"
 #include "Module.hh"
 
@@ -40,7 +41,8 @@ namespace module {
 namespace debug {
     
     class ActivePacketSource
-        : public Module
+        : public Module, 
+          public SafeBool<ActivePacketSource>
     {
     public:
         connector::ActiveOutput output;
@@ -48,6 +50,8 @@ namespace debug {
         ActivePacketSource();
 
         void submit(Packet packet);
+
+        bool boolean_test() const;
     };
 
     class PassivePacketSource
@@ -75,7 +79,8 @@ namespace debug {
     };
 
     class ActivePacketSink
-        : public Module
+        : public Module,
+          public SafeBool<ActivePacketSink>
     {
     public:
         connector::ActiveInput input;
@@ -83,6 +88,8 @@ namespace debug {
         ActivePacketSink();
 
         Packet request();
+
+        bool boolean_test() const;
     };
 
     class PassivePacketSink
diff --git a/PPI/Events.cc b/PPI/Events.cc
new file mode 100644 (file)
index 0000000..e5dc53a
--- /dev/null
@@ -0,0 +1,63 @@
+// $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 Events non-inline non-template implementation */
+
+#include "Events.hh"
+#include "Events.ih"
+
+// Custom includes
+#include "Route.hh"
+
+//#include "Events.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::EventDescriptor
+
+prefix_ void senf::ppi::EventDescriptor::notifyUnthrottle()
+{
+    Routes::const_iterator i (routes_.begin());
+    Routes::const_iterator const i_end (routes_.end());
+    for (; i != i_end; ++i)
+        if ((*i)->throttled())
+            break;
+    if (i == i_end) 
+        enabled(true);
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Events.mpp"
+
+\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 f511f40..600fc37 100644 (file)
@@ -65,12 +65,11 @@ prefix_ void senf::ppi::EventDescriptor::notifyThrottle()
     enabled(false);
 }
 
-prefix_ void senf::ppi::EventDescriptor::notifyUnthrottle()
+prefix_ void senf::ppi::EventDescriptor::registerRoute(ForwardingRoute & route)
 {
-    enabled(true);
+    routes_.push_back(&route);
 }
 
-
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index fffd59e..698a433 100644 (file)
@@ -25,6 +25,7 @@
 #define HH_Events_ 1
 
 // Custom includes
+#include <vector>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 #include "predecl.hh"
 
@@ -67,8 +68,13 @@ namespace ppi {
         void notifyThrottle();
         void notifyUnthrottle();
 
+        void registerRoute(ForwardingRoute & route);
+
         bool enabled_;
 
+        typedef std::vector<ForwardingRoute*> Routes;
+        Routes routes_;
+
         friend class ForwardingRoute;
     };
     
index f0e2279..252a37c 100644 (file)
@@ -47,6 +47,7 @@ prefix_ senf::ppi::RouteBase::RouteBase(module::Module & module)
 // senf::ppi::ForwardingRoute
 
 prefix_ bool senf::ppi::ForwardingRoute::autoThrottling()
+    const
 {
     return autoThrottling_;
 }
@@ -56,6 +57,12 @@ prefix_ void senf::ppi::ForwardingRoute::autoThrottling(bool state)
     autoThrottling_ = state;
 }
 
+prefix_ bool senf::ppi::ForwardingRoute::throttled()
+    const
+{
+    return v_throttled();
+}
+
 ////////////////////////////////////////
 // protected members
 
@@ -63,11 +70,6 @@ prefix_ senf::ppi::ForwardingRoute::ForwardingRoute(module::Module & module)
     : RouteBase(module), autoThrottling_(true)
 {}
 
-prefix_ void senf::ppi::ForwardingRoute::registerRoute(connector::ActiveConnector & connector)
-{
-    connector.registerRoute(*this);
-}
-
 ////////////////////////////////////////
 // private members
 
index fb1cc0c..fc6ef5b 100644 (file)
@@ -55,6 +55,15 @@ senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::v_notifyUnthrot
     }
 }
 
+template <class Source, class Target>
+prefix_ bool senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::v_throttled()
+    const
+{
+    return this->autoThrottling() && (
+        throttled(this->source(),boost::mpl::bool_<RoutingTraits<Source>::notifySource>()) ||
+        throttled(this->target(),boost::mpl::bool_<RoutingTraits<Target>::notifySource>()) );
+}
+
 ///////////////////////////////ct.e////////////////////////////////////////
 #undef prefix_
 
index a136aff..214468e 100644 (file)
@@ -46,6 +46,12 @@ prefix_ senf::ppi::Route<Source,Target>::Route(module::Module & module, Source &
 // protected members
 
 template <class T>
+prefix_ void senf::ppi::ForwardingRoute::registerRoute(T & ob)
+{
+    ob.registerRoute(*this);
+}
+
+template <class T>
 prefix_ void senf::ppi::ForwardingRoute::notifyThrottle(T & ob)
 {
     ob.notifyThrottle();
@@ -62,12 +68,14 @@ prefix_ void senf::ppi::ForwardingRoute::notifyUnthrottle(T & ob)
 
 template <class Source, class Target, class Base>
 prefix_ Source & senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::source()
+    const
 {
     return *source_;
 }
 
 template <class Source, class Target, class Base>
 prefix_ Target & senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::target()
+    const
 {
     return *target_;
 }
@@ -93,8 +101,8 @@ 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>());
+    registerRoute(source);
+    registerRoute(target);
 }
 
 ////////////////////////////////////////
@@ -103,44 +111,48 @@ ForwardingRouteImplementation(module::Module & module, Source & source, Target &
 template <class Source, class Target>
 template <class T>
 prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
-registerRoute(T & ob, boost::mpl::bool_<true> const &)
+notifyThrottle(T & ob, boost::mpl::bool_<true> const &)
 {
-    ForwardingRoute::registerRoute(ob);
+    ForwardingRoute::notifyThrottle(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 &)
+notifyThrottle(T & ob, boost::mpl::bool_<false> const &)
 {}
 
 template <class Source, class Target>
 template <class T>
 prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
-notifyThrottle(T & ob, boost::mpl::bool_<true> const &)
+notifyUnthrottle(T & ob, boost::mpl::bool_<true> const &)
 {
-    ForwardingRoute::notifyThrottle(ob);
+    ForwardingRoute::notifyUnthrottle(ob);
 }
 
 template <class Source, class Target>
 template <class T>
 prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
-notifyThrottle(T & ob, boost::mpl::bool_<false> const &)
+notifyUnthrottle(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 &)
+prefix_ bool senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+throttled(T & ob, boost::mpl::bool_<true> const &)
+    const
 {
-    ForwardingRoute::notifyUnthrottle(ob);
+    return ob.throttled();
 }
 
 template <class Source, class Target>
 template <class T>
-prefix_ void senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
-notifyUnthrottle(T & ob, boost::mpl::bool_<false> const &)
-{}
+prefix_ bool senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+throttled(T & ob, boost::mpl::bool_<false> const &)
+    const
+{
+    return false;
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::detail::RouteImplementation2<Source,Target>
index f765152..88722c2 100644 (file)
@@ -50,7 +50,7 @@ namespace ppi {
         : public RouteBase
     {
     public:
-        bool autoThrottling();
+        bool autoThrottling() const;
         void autoThrottling(bool state); ///< Change automatic throttle notification forwarding
                                         /**< By default, throttle notifications are automatically
                                              forwarded from active to passive connectors. This may
@@ -65,12 +65,14 @@ namespace ppi {
                                              comes in. Respective for unthrottle notifications.
 
                                              \param[in] state New throttle forwarding state */
+
+        bool throttled() const;
         
     protected:
         ForwardingRoute(module::Module & module);
 
         // Called to register this route with the connectors forwarding information base
-        void registerRoute(connector::ActiveConnector & connector);
+        template <class T> void registerRoute(T & ob);
 
         template <class T> void notifyThrottle(T & ob);
         template <class T> void notifyUnthrottle(T & ob);
@@ -83,6 +85,7 @@ namespace ppi {
         // Implemented in the derived classes to forward throttling notifications
         virtual void v_notifyThrottle() = 0;
         virtual void v_notifyUnthrottle() = 0;
+        virtual bool v_throttled() const = 0;
 
         bool autoThrottling_;
 
index 149b9e9..b99d93d 100644 (file)
@@ -97,8 +97,8 @@ namespace detail {
         typedef Source source_type;
         typedef Target target_type;
 
-        Source & source();
-        Target & target();
+        Source & source() const;
+        Target & target() const;
 
     protected:
         BaseRouteImplementation(module::Module & module, Source & source, Target & target);
@@ -131,18 +131,18 @@ namespace detail {
         ForwardingRouteImplementation(module::Module & module, Source & source, Target & target);
 
     private:
-        // 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 &);
-
         // 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 &);
 
+        template <class T> bool throttled(T & ob, boost::mpl::bool_<true> const &) const;
+        template <class T> bool throttled(T & ob, boost::mpl::bool_<false> const &) const;
+
         virtual void v_notifyThrottle();
         virtual void v_notifyUnthrottle();
+        virtual bool v_throttled() const;
     };
 
     // This helper class finds the base-class suitable for a specific route. Routes are classified
index 45b45ca..a70d869 100644 (file)
@@ -131,14 +131,13 @@ BOOST_AUTO_UNIT_TEST(route)
     BOOST_CHECK( ! tester.activeOut );
     BOOST_CHECK_EQUAL( tester.throttles, 1 );
     BOOST_CHECK( tester.passiveIn.throttled() );
-    BOOST_CHECK( ! activeSource.output );
+    BOOST_CHECK( ! activeSource );
     BOOST_CHECK( ! tester.event.enabled() );
 
     passiveSink.input.unthrottle();
-    BOOST_CHECK( activeSource.output );
+    BOOST_CHECK( activeSource );
     BOOST_CHECK( tester.event.enabled() );
     
-
     // Now throttle the passive source by exhausting the queue
     
     BOOST_CHECK( p1 == activeSink.request() );
@@ -146,18 +145,29 @@ BOOST_AUTO_UNIT_TEST(route)
     BOOST_CHECK( ! tester.activeIn );
     BOOST_CHECK_EQUAL( tester.throttles, 1 );
     BOOST_CHECK( tester.passiveOut.throttled() );
-    BOOST_CHECK( ! activeSink.input );
+    BOOST_CHECK( ! activeSink );
     BOOST_CHECK( ! tester.event.enabled() );
     
     passiveSource.submit(p1);
-    BOOST_CHECK( activeSink.input );
+    BOOST_CHECK( activeSink );
+    BOOST_CHECK( tester.event.enabled() );
+
+    // Check correct combination of multiple throttling events
+
+    activeSink.request();
+    BOOST_CHECK( ! tester.event.enabled() );
+    passiveSink.input.throttle();
+    BOOST_CHECK( ! tester.event.enabled() );
+    passiveSource.submit(p1);
+    BOOST_CHECK( ! tester.event.enabled() );
+    passiveSink.input.unthrottle();
     BOOST_CHECK( tester.event.enabled() );
 
     tester.rt->autoThrottling(false);
 
     BOOST_CHECK( p1 == activeSink.request() );
     BOOST_CHECK( passiveSource.output.throttled() );
-    BOOST_CHECK( activeSink.input );
+    BOOST_CHECK( activeSink );
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////