Route.ih
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief Route internal header */
16 
17 #ifndef IH_SENF_PPI_Route_
18 #define IH_SENF_PPI_Route_ 1
19 
20 // Custom includes
21 #include <boost/type_traits/is_convertible.hpp>
22 #include <boost/type_traits/is_base_of.hpp>
23 #include <boost/mpl/if.hpp>
24 #include <boost/mpl/bool.hpp>
25 #include <boost/static_assert.hpp>
26 
27 //-/////////////////////////////////////////////////////////////////////////////////////////////////
28 
29 #ifndef DOXYGEN
30 
31 namespace senf {
32 namespace ppi {
33 namespace detail {
34 
35  // This is the RoutingTraits implementation for Connectors. Events are handled in the
36  // specialization below
37  template <class Connector, bool isEvent>
38  struct RoutingTraitsImplementation
39  {
40  BOOST_STATIC_ASSERT((boost::is_base_of<connector::Connector, Connector>::value));
41 
42  static bool const event = false;
43 
44  static bool const notifySource = boost::is_base_of<
45  connector::ActiveConnector, Connector>::value;
46  static bool const notifyTarget = boost::is_base_of<
47  connector::PassiveConnector, Connector>::value;
48 
49  static bool const dataSource = boost::is_base_of<
50  connector::InputConnector, Connector>::value;
51  static bool const dataTarget = boost::is_base_of<
52  connector::OutputConnector, Connector>::value;
53 
54  typedef Connector type;
55  };
56 
57  // RoutingTraits specialization for Event types. Events may be both dataSource or dataTarget but
58  // cannot be notifySource.
59  template <class Event>
60  struct RoutingTraitsImplementation<Event,true>
61  {
62  static bool const event = true;
63 
64  static bool const notifySource = false;
65  static bool const notifyTarget = true;
66 
67  static bool const dataSource = true;
68  static bool const dataTarget = true;
69 
70  typedef EventDescriptor type;
71  };
72 
73  // The RoutingTraits give routing related information about the argument type:
74  // - Whether the type is a notifySource or notifyTarget
75  // - Whether the type is dataSource or dataTarget
76  // - Provide the generalized target type
77  //
78  // The real implementation is in RoutingTraitsImplementation which is appropriately specialized
79  // for Events
80  template <class Object>
81  struct RoutingTraits
82  : public RoutingTraitsImplementation<Object,
83  boost::is_convertible<Object*,
84  EventDescriptor*>::value>
85  {};
86 
87  // This is the generic route implementation for all routes. It just provides access to the
88  // source and target.
89  template <class Source, class Target, class Base>
90  class BaseRouteImplementation
91  : public Base
92  {
93  protected:
94  typedef Source source_type;
95  typedef Target target_type;
96 
97  Source & source() const;
98  Target & target() const;
99 
100  BaseRouteImplementation(Source & source, Target & target);
101 
102  private:
103  bool v_hasConnector(connector::Connector const & conn) const;
104  bool v_hasEvent(EventDescriptor const & event) const;
105 
106  bool isSame(connector::Connector const & conn, connector::Connector const & other) const;
107  bool isSame(connector::Connector const & conn, EventDescriptor const & other) const;
108  bool isSame(EventDescriptor const & event, connector::Connector const & other) const;
109  bool isSame(EventDescriptor const & event, EventDescriptor const & other) const;
110 
111  Source * source_;
112  Target * target_;
113  };
114 
115  // The ForwardingRouteImplementation is based on the same BaseRouteImplementation
116  // as non-forwarding routes are but injects a different base-class (the third template
117  // argument to BaseRouteImplementation). ForwardingRouteImplementation has two additional
118  // functions:
119  // 1) Register the ForwardingRoute with the notifySource
120  // 2) Implement the abstract ForwardingRoute interface
121  //
122  // Since we don't know explicitly, which of Source or Target is the notifySource or
123  // notifyTarget, the implementation calls registerRoute and notifyThrottle/notifyUnthrottle on
124  // *both*, the source and target, however qualified with an additional argument of type
125  // boost::mpl::bool_ which is used to select the correct overloads, of which the 'false'
126  // overload always is a no-op. This way, only the correct call will generate any code, the
127  // disabled call will be optimized away.
128  template <class Source, class Target>
129  class ForwardingRouteImplementation
130  : public BaseRouteImplementation<Source, Target, ForwardingRoute>
131  {
132  typedef BaseRouteImplementation<Source, Target, ForwardingRoute> Base;
133 
134  protected:
135  ForwardingRouteImplementation(Source & source, Target & target);
136  ~ForwardingRouteImplementation();
137 
138  private:
139  // send a throttle/unthrottle notification only if the second argument is a 'true' type
140  template <class T> void notifyThrottle(T & ob, boost::mpl::bool_<true> const &);
141  template <class T> void notifyThrottle(T & ob, boost::mpl::bool_<false> const &);
142  template <class T> void notifyUnthrottle(T & ob, boost::mpl::bool_<true> const &);
143  template <class T> void notifyUnthrottle(T & ob, boost::mpl::bool_<false> const &);
144 
145  template <class T> bool throttled(T & ob, boost::mpl::bool_<true> const &) const;
146  template <class T> bool throttled(T & ob, boost::mpl::bool_<false> const &) const;
147 
148  virtual void v_notifyThrottle();
149  virtual void v_notifyUnthrottle();
150  virtual bool v_throttled() const;
151  };
152 
153  // This helper class finds the base-class suitable for a specific route. Routes are classified
154  // into two groups:
155  // 1) A forwarding routes is a routed which forwards notifications from a notifySource to a
156  // notifyTarget. Forwarding routes are implemented using ForwardingRouteImplementation
157  // 2) Non-forwarding routes don't forward notifications. They are implemented directly
158  // using BaseRouteImplementation
159  template <class Source, class Target>
160  struct RouteImplementationBase
161  {
162  typedef RoutingTraits<Source> srcTrait;
163  typedef RoutingTraits<Target> trgTrait;
164 
165  static bool const isForwarding = (srcTrait::notifySource && trgTrait::notifyTarget)
166  || (srcTrait::notifyTarget && trgTrait::notifySource);
167 
168  typedef typename boost::mpl::if_c<
169  isForwarding,
170  ForwardingRouteImplementation<Source,Target>,
171  BaseRouteImplementation<Source,Target,RouteBase> >::type base;
172  };
173 
174  // RouteImplementation2 has two purposes:
175  // 1) Ensure, that routing is always from a data source to a data target
176  // 2) To find the correct base-class. This is delegated to RouteImplementationBase
177  template <class Source, class Target>
178  class RouteImplementation2
179  : public RouteImplementationBase<Source,Target>::base
180  {
181  typedef typename RouteImplementationBase<Source,Target>::base Base;
182 
183  BOOST_STATIC_ASSERT( RoutingTraits<Source>::dataSource &&
184  RoutingTraits<Target>::dataTarget );
185 
186  protected:
187  RouteImplementation2(Source & source, Target & target);
188  };
189 
190  // RouteImplementation just forwards to RouteImplementation2 replacing the template arguments
191  // with the appropriately generalized type: If either Source or Target is an Event type, it is
192  // replaced with the general Event base-class EventDescriptor. Connector types are left as is.
193  template <class Source, class Target>
194  class RouteImplementation
195  : public RouteImplementation2<typename RoutingTraits<Source>::type,
196  typename RoutingTraits<Target>::type>
197  {
198  typedef RouteImplementation2<typename RoutingTraits<Source>::type,
199  typename RoutingTraits<Target>::type> Base;
200 
201  protected:
202  RouteImplementation(Source & source, Target & target);
203  };
204 
205 }}}
206 
207 #endif
208 
209 //-/////////////////////////////////////////////////////////////////////////////////////////////////
210 #endif
211 
212 
213 // Local Variables:
214 // mode: c++
215 // fill-column: 100
216 // comment-column: 40
217 // c-file-style: "senf"
218 // indent-tabs-mode: nil
219 // ispell-local-dictionary: "american"
220 // compile-command: "scons -u test"
221 // End: