From: g0dil Date: Tue, 14 Aug 2007 14:30:29 +0000 (+0000) Subject: PPI: Implement DebugEvent X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=7465ea4f6d3d54622bd783106cf8b60d5f133343;p=senf.git PPI: Implement DebugEvent 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 --- diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index 6e01ca3..24b3bed 100644 --- a/PPI/Connectors.hh +++ b/PPI/Connectors.hh @@ -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 index 0000000..df9bad5 --- /dev/null +++ b/PPI/DebugEvent.cci @@ -0,0 +1,61 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_ + + +// 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 index 0000000..3a2f254 --- /dev/null +++ b/PPI/DebugEvent.hh @@ -0,0 +1,86 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 + + +// 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/DebugModules.cci b/PPI/DebugModules.cci index aa2a49e..58f367d 100644 --- a/PPI/DebugModules.cci +++ b/PPI/DebugModules.cci @@ -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; } diff --git a/PPI/DebugModules.hh b/PPI/DebugModules.hh index 3ff2548..8730ad7 100644 --- a/PPI/DebugModules.hh +++ b/PPI/DebugModules.hh @@ -103,8 +103,8 @@ namespace debug { iterator begin(); iterator end(); - Packet back(); - Packet pop_back(); + Packet front(); + Packet pop_front(); void clear(); diff --git a/PPI/DebugModules.test.cc b/PPI/DebugModules.test.cc index 3f19899..0fc70cc 100644 --- a/PPI/DebugModules.test.cc +++ b/PPI/DebugModules.test.cc @@ -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() ); } diff --git a/PPI/EventManager.hh b/PPI/EventManager.hh index 46631e6..0c428ca 100644 --- a/PPI/EventManager.hh +++ b/PPI/EventManager.hh @@ -55,7 +55,7 @@ namespace ppi { // struct is called 'Callback' and will hang in an endless loop somewhere struct Callback_ #endif - : public detail::Callback + : public detail::Callback {}; /////////////////////////////////////////////////////////////////////////// diff --git a/PPI/Events.cci b/PPI/Events.cci index 8ffd90e..f511f40 100644 --- a/PPI/Events.cci +++ b/PPI/Events.cci @@ -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_ diff --git a/PPI/Events.cti b/PPI/Events.cti index a7db87c..428e2cd 100644 --- a/PPI/Events.cti +++ b/PPI/Events.cti @@ -32,34 +32,80 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::ppi::EventImplementation +// senf::ppi::EventImplementationHelper //////////////////////////////////////// // protected members -template -prefix_ senf::ppi::EventImplementation::EventImplementation() - : binding_(0) -{} +template +prefix_ void +senf::ppi::EventImplementationHelper::callback(EventArg event, + boost::posix_time::ptime time) +{ + binding().callback(event,time); +} -template -prefix_ void senf::ppi::EventImplementation::callback(EventArg event, - boost::posix_time::ptime time) +template +prefix_ void senf::ppi::EventImplementationHelper::callback(EventArg event) { - BOOST_ASSERT(binding_); - binding_->callback(event,time); + binding().callback(event); } -template -prefix_ void senf::ppi::EventImplementation::callback(EventArg event) +//////////////////////////////////////// +// private members + +template +prefix_ senf::ppi::detail::EventBinding & +senf::ppi::EventImplementationHelper::binding() +{ + BOOST_ASSERT( static_cast(this)->binding_ ); + return * static_cast(this)->binding_; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::ppi::EventImplementationHelper + +//////////////////////////////////////// +// protected members + +template +prefix_ void +senf::ppi::EventImplementationHelper::callback(boost::posix_time::ptime time) +{ + binding().callback(time); +} + +template +prefix_ void senf::ppi::EventImplementationHelper::callback() { - BOOST_ASSERT(binding_); - binding_->callback(event); + binding().callback(); } //////////////////////////////////////// // private members +template +prefix_ senf::ppi::detail::EventBinding & +senf::ppi::EventImplementationHelper::binding() +{ + BOOST_ASSERT( static_cast(this)->binding_ ); + return * static_cast(this)->binding_; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::ppi::EventImplementation + +//////////////////////////////////////// +// protected members + +template +prefix_ senf::ppi::EventImplementation::EventImplementation() + : binding_(0) +{} + +//////////////////////////////////////// +// private members + template prefix_ bool senf::ppi::EventImplementation::v_isRegistered() { diff --git a/PPI/Events.hh b/PPI/Events.hh index cb21dd7..fffd59e 100644 --- a/PPI/Events.hh +++ b/PPI/Events.hh @@ -64,12 +64,42 @@ namespace ppi { virtual bool v_isRegistered() = 0; + void notifyThrottle(); + void notifyUnthrottle(); + bool enabled_; + + friend class ForwardingRoute; + }; + + template + class EventImplementationHelper + { + protected: + typedef typename detail::EventArgType::type EventArg; + + void callback(EventArg event, boost::posix_time::ptime time); + void callback(EventArg event); + + private: + detail::EventBinding & binding(); + }; + + template + class EventImplementationHelper + { + protected: + void callback(boost::posix_time::ptime time); + void callback(); + + private: + detail::EventBinding & binding(); }; template class EventImplementation - : public EventDescriptor + : public EventDescriptor, + public EventImplementationHelper< EventType, EventImplementation > { 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 & binding); @@ -88,6 +115,7 @@ namespace ppi { detail::EventBinding * binding_; friend class EventManager; + friend class EventImplementationHelper< EventType, EventImplementation >; }; }} diff --git a/PPI/Route.cci b/PPI/Route.cci index 01c6f3a..f0e2279 100644 --- a/PPI/Route.cci +++ b/PPI/Route.cci @@ -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 - -prefix_ -senf::ppi::detail::RouteImplementation:: -RouteImplementation(module::Module & module, connector::ActiveInput & source, - connector::PassiveOutput & target) - : ForwardForwardingRouteImplementation(module, source, target) -{} - -//////////////////////////////////////////////////////////////////////////// -// senf::ppi::detail::RouteImplementation - -prefix_ -senf::ppi::detail::RouteImplementation:: -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 index 0000000..fb1cc0c --- /dev/null +++ b/PPI/Route.ct @@ -0,0 +1,70 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 + +//////////////////////////////////////// +// private members + +template +prefix_ void senf::ppi::detail::ForwardingRouteImplementation::v_notifyThrottle() +{ + if (this->autoThrottling()) { + notifyThrottle(this->source(),boost::mpl::bool_::notifyTarget>()); + notifyThrottle(this->target(),boost::mpl::bool_::notifyTarget>()); + } +} + +template +prefix_ void +senf::ppi::detail::ForwardingRouteImplementation::v_notifyUnthrottle() +{ + if (this->autoThrottling()) { + notifyUnthrottle(this->source(),boost::mpl::bool_::notifyTarget>()); + notifyUnthrottle(this->target(),boost::mpl::bool_::notifyTarget>()); + } +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/Route.cti b/PPI/Route.cti index 015ea90..a136aff 100644 --- a/PPI/Route.cti +++ b/PPI/Route.cti @@ -31,65 +31,139 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::ppi::detail::RouteImplementation +// senf::ppi::Route -template -prefix_ -senf::ppi::detail::RouteImplementation:: -RouteImplementation(module::Module & module, Source & source, Target & target) - : NonForwardingRouteImplementation(module, source, target) +template +prefix_ senf::ppi::Route::Route(module::Module & module, Source & source, + Target & target) + : Base(module,source,target) {} /////////////////////////////////////////////////////////////////////////// -// senf::ppi::detail::RouteImplementation +// senf::ppi::ForwardingRoute -template -prefix_ -senf::ppi::detail::RouteImplementation:: -RouteImplementation(module::Module & module, Source & source, Target & target) - : NonForwardingRouteFromEventImplementation(module, source, target) +//////////////////////////////////////// +// protected members + +template +prefix_ void senf::ppi::ForwardingRoute::notifyThrottle(T & ob) +{ + ob.notifyThrottle(); +} + +template +prefix_ void senf::ppi::ForwardingRoute::notifyUnthrottle(T & ob) +{ + ob.notifyUnthrottle(); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::ppi::detail::BaseRouteImplementation + +template +prefix_ Source & senf::ppi::detail::BaseRouteImplementation::source() +{ + return *source_; +} + +template +prefix_ Target & senf::ppi::detail::BaseRouteImplementation::target() +{ + return *target_; +} + +//////////////////////////////////////// +// protected members + +template +prefix_ senf::ppi::detail::BaseRouteImplementation:: +BaseRouteImplementation(module::Module & module, Source & source, Target & target) + : Base(module), source_(&source), target_(&target) {} /////////////////////////////////////////////////////////////////////////// -// senf::ppi::detail::RouteImplementation +// senf::ppi::detail::ForwardingRouteImplementation + +//////////////////////////////////////// +// protected members template prefix_ -senf::ppi::detail::RouteImplementation:: -RouteImplementation(module::Module & module, Source & source, Target & target) - : NonForwardingRouteToEventImplementation(module, source, target) +senf::ppi::detail::ForwardingRouteImplementation:: +ForwardingRouteImplementation(module::Module & module, Source & source, Target & target) + : Base(module,source,target) +{ + registerRoute(source, boost::mpl::bool_::notifySource>()); + registerRoute(target, boost::mpl::bool_::notifySource>()); +} + +//////////////////////////////////////// +// private members + +template +template +prefix_ void senf::ppi::detail::ForwardingRouteImplementation:: +registerRoute(T & ob, boost::mpl::bool_ const &) +{ + ForwardingRoute::registerRoute(ob); +} + +template +template +prefix_ void senf::ppi::detail::ForwardingRouteImplementation:: +registerRoute(T & ob, boost::mpl::bool_ const &) {} -/////////////////////////////////////////////////////////////////////////// -// senf::ppi::detail::RouteImplementation +template +template +prefix_ void senf::ppi::detail::ForwardingRouteImplementation:: +notifyThrottle(T & ob, boost::mpl::bool_ const &) +{ + ForwardingRoute::notifyThrottle(ob); +} -template -prefix_ -senf::ppi::detail::RouteImplementation:: -RouteImplementation(module::Module & module, connector::ActiveInput & source, Event & target) - : ForwardForwardingRouteToEventImplementation(module, source, target) +template +template +prefix_ void senf::ppi::detail::ForwardingRouteImplementation:: +notifyThrottle(T & ob, boost::mpl::bool_ const &) +{} + +template +template +prefix_ void senf::ppi::detail::ForwardingRouteImplementation:: +notifyUnthrottle(T & ob, boost::mpl::bool_ const &) +{ + ForwardingRoute::notifyUnthrottle(ob); +} + +template +template +prefix_ void senf::ppi::detail::ForwardingRouteImplementation:: +notifyUnthrottle(T & ob, boost::mpl::bool_ const &) {} /////////////////////////////////////////////////////////////////////////// -// senf::ppi::detail::RouteImplementation +// senf::ppi::detail::RouteImplementation2 -template -prefix_ -senf::ppi::detail::RouteImplementation:: -RouteImplementation(module::Module & module, Event & source, connector::ActiveOutput & target) - : BackwardForwardingRouteFromEventImplementation(module, source, target) +//////////////////////////////////////// +// protected members + +template +prefix_ senf::ppi::detail::RouteImplementation2:: +RouteImplementation2(module::Module & module, Source & source, Target & target) + : Base(module,source,target) {} /////////////////////////////////////////////////////////////////////////// -// senf::ppi::Route +// senf::ppi::detail::RouteImplementation //////////////////////////////////////// // protected members template -prefix_ senf::ppi::Route::Route(module::Module & module, Source & source, - Target & target) - : Implementation(module, source, target) +prefix_ senf::ppi::detail::RouteImplementation:: +RouteImplementation(module::Module & module, Source & source, Target & target) + : Base(module,source,target) {} ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/PPI/Route.hh b/PPI/Route.hh index e3eee1c..f765152 100644 --- a/PPI/Route.hh +++ b/PPI/Route.hh @@ -72,6 +72,9 @@ namespace ppi { // Called to register this route with the connectors forwarding information base void registerRoute(connector::ActiveConnector & connector); + template void notifyThrottle(T & ob); + template 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 { + typedef detail::RouteImplementation Base; private: typedef detail::RouteImplementation Implementation; @@ -115,7 +119,7 @@ namespace ppi { ///////////////////////////////hh.e//////////////////////////////////////// #include "Route.cci" -//#include "Route.ct" +#include "Route.ct" #include "Route.cti" #endif diff --git a/PPI/Route.ih b/PPI/Route.ih index 1e76429..149b9e9 100644 --- a/PPI/Route.ih +++ b/PPI/Route.ih @@ -27,6 +27,11 @@ #define IH_Route_ 1 // Custom includes +#include +#include +#include +#include +#include ///////////////////////////////ih.p//////////////////////////////////////// @@ -34,185 +39,164 @@ namespace senf { namespace ppi { namespace detail { - // Valid Forwarding routes: - // Forward throttling - // ActiveInput -> PassiveOutput - // tempalte<> RouteImplementation - // ActiveInput -> Event - // template class RouteImplementation - // Backward throttling - // PassiveInput -> ActiveOutput - // template<> RouteImplementation - // Event -> ActiveOutput - // template class RouteImplementation - - class NonForwardingRouteImplementation - : public RouteBase + // This is the RoutingTraits implementation for Connectors. Events are handled in the + // specialization below + template + struct RoutingTraitsImplementation { - protected: - NonForwardingRouteImplementation(module::Module & module, - connector::InputConnector & source, - connector::OutputConnector & target); + BOOST_STATIC_ASSERT((boost::is_base_of::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 + struct RoutingTraitsImplementation { - 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 + struct RoutingTraits + : public RoutingTraitsImplementation::value> + {}; + + // This is the generic route implementation for all routes. It just provides access to the + // source and target. + template + 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 ForwardingRouteImplementation + : public BaseRouteImplementation { + typedef BaseRouteImplementation 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 void registerRoute(T & ob, boost::mpl::bool_ const &); + template void registerRoute(T & ob, boost::mpl::bool_ 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 void notifyThrottle(T & ob, boost::mpl::bool_ const &); + template void notifyThrottle(T & ob, boost::mpl::bool_ const &); + template void notifyUnthrottle(T & ob, boost::mpl::bool_ const &); + template void notifyUnthrottle(T & ob, boost::mpl::bool_ const &); - private: virtual void v_notifyThrottle(); virtual void v_notifyUnthrottle(); - - EventDescriptor * source_; - connector::ActiveOutput * target_; }; - template - 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 + struct RouteImplementationBase { - protected: - RouteImplementation(module::Module & module, Source & source, Target & target); - }; + typedef RoutingTraits srcTrait; + typedef RoutingTraits trgTrait; -# ifndef DOXYGEN + static bool const isForwarding = (srcTrait::notifySource && trgTrait::notifyTarget) + || (srcTrait::notifyTarget && trgTrait::notifySource); + + typedef typename boost::mpl::if_c< + isForwarding, + ForwardingRouteImplementation, + BaseRouteImplementation >::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 RouteImplementation - : public NonForwardingRouteFromEventImplementation + class RouteImplementation2 + : public RouteImplementationBase::base { - protected: - RouteImplementation(module::Module & module, Source & source, Target & target); - }; + typedef typename RouteImplementationBase::base Base; - template - class RouteImplementation - : public NonForwardingRouteToEventImplementation - { - protected: - RouteImplementation(module::Module & module, Source & source, Target & target); - }; + BOOST_STATIC_ASSERT( RoutingTraits::dataSource && + RoutingTraits::dataTarget ); - template<> - class RouteImplementation - : public ForwardForwardingRouteImplementation - { protected: - RouteImplementation(module::Module & module, connector::ActiveInput & source, - connector::PassiveOutput & target); + RouteImplementation2(module::Module & module, Source & source, Target & target); }; - template - class RouteImplementation - : 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 RouteImplementation + : public RouteImplementation2::type, + typename RoutingTraits::type> { - protected: - RouteImplementation(module::Module & module, connector::ActiveInput & source, - Event & target); - }; + typedef RouteImplementation2::type, + typename RoutingTraits::type> Base; - template <> - class RouteImplementation - : public BackwardForwardingRouteImplementation - { protected: - RouteImplementation(module::Module & module, connector::PassiveInput & source, - connector::ActiveOutput & target); - }; - - template - class RouteImplementation - : public BackwardForwardingRouteFromEventImplementation - { - protected: - RouteImplementation(module::Module & module, Event & source, - connector::ActiveOutput & target); + RouteImplementation(module::Module & module, Source & source, Target & target); }; -# endif - }}} ///////////////////////////////ih.e//////////////////////////////////////// diff --git a/PPI/Route.test.cc b/PPI/Route.test.cc index 2337e9e..45b45ca 100644 --- a/PPI/Route.test.cc +++ b/PPI/Route.test.cc @@ -28,6 +28,10 @@ // Custom includes #include "Route.hh" +#include "DebugEvent.hh" +#include "DebugModules.hh" +#include "Module.hh" +#include "Setup.hh" #include #include @@ -35,8 +39,126 @@ #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_ diff --git a/PPI/detail/EventBinding.cti b/PPI/detail/EventBinding.cti index aeb0555..f37637e 100644 --- a/PPI/detail/EventBinding.cti +++ b/PPI/detail/EventBinding.cti @@ -31,6 +31,59 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// +// senf::ppi::detail::EventBindingHelper + +template +prefix_ void +senf::ppi::detail::EventBindingHelper::callback(EventArg event, + boost::posix_time::ptime time) +{ + self().eventTime(time); + self().callback_(event); +} + +template +prefix_ void senf::ppi::detail::EventBindingHelper::callback(EventArg event) +{ + callback(event, boost::posix_time::microsec_clock::universal_time()); +} + +//////////////////////////////////////// +// private members + +template +prefix_ Self & senf::ppi::detail::EventBindingHelper::self() +{ + return * static_cast(this); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::ppi::detail::EventBindingHelper + +template +prefix_ void +senf::ppi::detail::EventBindingHelper::callback(boost::posix_time::ptime time) +{ + self().eventTime(time); + self().callback_(); +} + +template +prefix_ void senf::ppi::detail::EventBindingHelper::callback() +{ + callback(boost::posix_time::microsec_clock::universal_time()); +} + +//////////////////////////////////////// +// private members + +template +prefix_ Self & senf::ppi::detail::EventBindingHelper::self() +{ + return * static_cast(this); +} + +/////////////////////////////////////////////////////////////////////////// // senf::ppi::detail::EventBinding template @@ -41,20 +94,6 @@ prefix_ senf::ppi::detail::EventBinding::EventBinding(EventManager & : EventBindingBase(manager, module, descriptor), callback_(callback) {} -template -prefix_ void senf::ppi::detail::EventBinding::callback(EventArg event, - boost::posix_time::ptime time) -{ - eventTime(time); - callback_(event); -} - -template -prefix_ void senf::ppi::detail::EventBinding::callback(EventArg event) -{ - callback(event, boost::posix_time::microsec_clock::universal_time()); -} - ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/PPI/detail/EventBinding.hh b/PPI/detail/EventBinding.hh index 10959d7..addda33 100644 --- a/PPI/detail/EventBinding.hh +++ b/PPI/detail/EventBinding.hh @@ -52,23 +52,47 @@ namespace detail { EventDescriptor * descriptor_; }; + template + class EventBindingHelper + { + public: + typedef typename detail::EventArgType::type EventArg; + + void callback(EventArg event, boost::posix_time::ptime time); + void callback(EventArg event); + + private: + Self & self(); + }; + + template + class EventBindingHelper + { + public: + void callback(boost::posix_time::ptime time); + void callback(); + + private: + Self & self(); + }; + template class EventBinding - : public EventBindingBase + : public EventBindingBase, + public EventBindingHelper > { public: typedef EventType Event; typedef typename detail::EventArgType::type EventArg; - typedef typename detail::Callback::type Callback; + typedef typename detail::Callback::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 >; }; }}} diff --git a/PPI/predecl.hh b/PPI/predecl.hh index be9c053..2b8f6ea 100644 --- a/PPI/predecl.hh +++ b/PPI/predecl.hh @@ -55,9 +55,7 @@ namespace ppi { class BackwardForwardingRouteImplementation; class ForwardForwardingRouteToEventImplementation; class BackwardForwardingRouteFromEventImplementation; - template ::value, - bool trgEvent = boost::is_base_of::value> + template class RouteImplementation; }