X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=PPI%2FRoute.ih;h=31a4e5b31f8e7785126ace7fc9106633c7b965e2;hb=5443435c4c2b6e4386c5334b5b8358273f2bae93;hp=b3de6abc034da32c5ec4fb9824f06d2f712c7a01;hpb=81ffa1c459b96dd44472bcef37e1e373934ee138;p=senf.git diff --git a/PPI/Route.ih b/PPI/Route.ih index b3de6ab..31a4e5b 100644 --- a/PPI/Route.ih +++ b/PPI/Route.ih @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -23,61 +23,190 @@ /** \file \brief Route internal header */ -#ifndef IH_Route_ -#define IH_Route_ 1 +#ifndef IH_SENF_PPI_Route_ +#define IH_SENF_PPI_Route_ 1 // Custom includes +#include +#include +#include +#include +#include ///////////////////////////////ih.p//////////////////////////////////////// +#ifndef DOXYGEN + namespace senf { namespace ppi { namespace detail { - template - class RouteImplementation - : public RouteBase + // This is the RoutingTraits implementation for Connectors. Events are handled in the + // specialization below + template + struct RoutingTraitsImplementation + { + BOOST_STATIC_ASSERT((boost::is_base_of::value)); + + static bool const event = false; + + static bool const notifySource = boost::is_base_of< + connector::ActiveConnector, Connector>::value; + static bool const notifyTarget = boost::is_base_of< + connector::PassiveConnector, Connector>::value; + + static bool const dataSource = boost::is_base_of< + connector::InputConnector, Connector>::value; + static bool const dataTarget = boost::is_base_of< + connector::OutputConnector, Connector>::value; + + typedef Connector type; + }; + + // RoutingTraits specialization for Event types. Events may be both dataSource or dataTarget but + // cannot be notifySource. + template + struct RoutingTraitsImplementation + { + static bool const event = true; + + static bool const notifySource = false; + static bool const notifyTarget = true; + + static bool const dataSource = true; + static bool const dataTarget = true; + + 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 { + public: + typedef Source source_type; + typedef Target target_type; + + Source & source() const; + Target & target() const; + protected: - RouteImplementation(module::Module & module, - connector::InputConnector & source, - connector::OutputConnector & target); + BaseRouteImplementation(module::Module & module, Source & source, Target & target); private: - connector::InputConnector * source_; - connector::OutputConnector * target_; + Source * source_; + Target * target_; }; - template <> - class RouteImplementation - : public RouteBase + // 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: - RouteImplementation(module::Module & module, - EventDescriptor & source, - connector::OutputConnector & target); + ForwardingRouteImplementation(module::Module & module, Source & source, Target & target); private: - EventDescriptor * source_; - connector::OutputConnector * 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 &); + + template bool throttled(T & ob, boost::mpl::bool_ const &) const; + template bool throttled(T & ob, boost::mpl::bool_ 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 + // 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 + { + typedef RoutingTraits srcTrait; + typedef RoutingTraits trgTrait; + + static bool const isForwarding = (srcTrait::notifySource && trgTrait::notifyTarget) + || (srcTrait::notifyTarget && trgTrait::notifySource); + + typedef typename boost::mpl::if_c< + isForwarding, + ForwardingRouteImplementation, + BaseRouteImplementation >::type base; }; - template<> - class RouteImplementation - : public RouteBase + // 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 RouteImplementation2 + : public RouteImplementationBase::base { + typedef typename RouteImplementationBase::base Base; + + BOOST_STATIC_ASSERT( RoutingTraits::dataSource && + RoutingTraits::dataTarget ); + protected: - RouteImplementation(module::Module & module, - connector::InputConnector & source, - EventDescriptor & target); + RouteImplementation2(module::Module & module, Source & source, Target & target); + }; - private: - connector::InputConnector * source_; - EventDescriptor * target_; + // 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> + { + typedef RouteImplementation2::type, + typename RoutingTraits::type> Base; + + protected: + RouteImplementation(module::Module & module, Source & source, Target & target); }; }}} +#endif + ///////////////////////////////ih.e//////////////////////////////////////// #endif