// $Id$ // // Copyright (C) 2007 // Fraunhofer Institute for Open Communication Systems (FOKUS) // // The contents of this file are subject to the Fraunhofer FOKUS Public License // Version 1.0 (the "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // http://senf.berlios.de/license.html // // The Fraunhofer FOKUS Public License Version 1.0 is based on, // but modifies the Mozilla Public License Version 1.1. // See the full license text for the amendments. // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License // for the specific language governing rights and limitations under the License. // // The Original Code is Fraunhofer FOKUS code. // // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. // (registered association), Hansastraße 27 c, 80686 Munich, Germany. // All Rights Reserved. // // Contributor(s): // Stefan Bund /** \file \brief Route internal header */ #ifndef IH_SENF_PPI_Route_ #define IH_SENF_PPI_Route_ 1 // Custom includes #include #include #include #include #include //-///////////////////////////////////////////////////////////////////////////////////////////////// #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: // - Whether the type is a notifySource or notifyTarget // - Whether 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: typedef Source source_type; typedef Target target_type; Source & source() const; Target & target() const; BaseRouteImplementation(module::Module & module, Source & source, Target & target); private: bool v_hasConnector(connector::Connector const & conn) const; bool v_hasEvent(EventDescriptor const & event) const; bool isSame(connector::Connector const & conn, connector::Connector const & other) const; bool isSame(connector::Connector const & conn, EventDescriptor const & other) const; bool isSame(EventDescriptor const & event, connector::Connector const & other) const; bool isSame(EventDescriptor const & event, EventDescriptor const & other) const; 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); ~ForwardingRouteImplementation(); 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 implemented 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 //-///////////////////////////////////////////////////////////////////////////////////////////////// #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: