// $Id$ // // 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 // 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 internal header */ #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 { // 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: BaseRouteImplementation(module::Module & module, Source & source, Target & target); private: Source * source_; Target * target_; }; // 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: ForwardingRouteImplementation(module::Module & module, Source & source, Target & target); private: // 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; }; // 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: RouteImplementation2(module::Module & module, Source & source, Target & 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 // 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: