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
--- /dev/null
+// $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:
--- /dev/null
+// $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:
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;
}
iterator begin();
iterator end();
- Packet back();
- Packet pop_back();
+ Packet front();
+ Packet pop_front();
void clear();
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() );
}
// 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>
{};
///////////////////////////////////////////////////////////////////////////
: enabled_(false)
{}
+////////////////////////////////////////
+// private members
+
+prefix_ void senf::ppi::EventDescriptor::notifyThrottle()
+{
+ enabled(false);
+}
+
+prefix_ void senf::ppi::EventDescriptor::notifyUnthrottle()
+{
+ enabled(true);
+}
+
+
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
///////////////////////////////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()
{
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;
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);
detail::EventBinding<Event> * binding_;
friend class EventManager;
+ friend class EventImplementationHelper< EventType, EventImplementation<EventType> >;
};
}}
// 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)
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_
--- /dev/null
+// $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:
///////////////////////////////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///////////////////////////////////////
// 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();
class Route
: public detail::RouteImplementation<Source,Target>
{
+ typedef detail::RouteImplementation<Source,Target> Base;
private:
typedef detail::RouteImplementation<Source,Target> Implementation;
///////////////////////////////hh.e////////////////////////////////////////
#include "Route.cci"
-//#include "Route.ct"
+#include "Route.ct"
#include "Route.cti"
#endif
#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////////////////////////////////////////
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////////////////////////////////////////
// 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_
///////////////////////////////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>
: 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_
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> >;
};
}}}
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;
}