2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.de>
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 \brief Connectors public header */
24 /** \defgroup connectors Connector classes
26 A connector has two independent properties
27 \li it may be \e active or \e passive
28 \li it may be an \e input or an \e output
30 \e Active connectors are activated from within the module, \e passive connectors are signaled by
31 the external framework. \e Input modules receive packets, \e output modules send packets.
33 All passive connectors call some onRequest callback whenever I/O needs to be performed. All
34 input modules possess a packet queue.
36 We therefore have 4 connector types: senf::ppi::ActiveInput, senf::ppi::ActiveOutput,
37 senf::ppi::PassiveInput and senf::ppi::PassiveOutput.
40 #ifndef HH_Connectors_
41 #define HH_Connectors_ 1
45 #include <boost/utility.hpp>
46 #include <boost/scoped_ptr.hpp>
47 #include "Utils/SafeBool.hh"
48 #include "Packets/Packets.hh"
50 #include "detail/Callback.hh"
51 #include "Queueing.hh"
53 //#include "Connectors.mpp"
54 ///////////////////////////////hh.p////////////////////////////////////////
60 /** \namespace senf::ppi::connector
61 \brief Connector classes
64 /** \brief Connector base-class
66 This connector provides access to the generic connector facilities. This includes the
67 connection management (access to the connected peer) and the containment management (access
68 to the containing module)
74 Connector & peer() const; ///< Get peer connected to this connector
75 module::Module & module() const; ///< Get this connectors containing module
81 void connect(Connector & target);
84 void setModule(module::Module & module);
87 module::Module * module_;
89 friend class module::Module;
92 /** \brief Passive connector base-class
94 A passive connector is a connector which is activated externally whenever an I/O request
95 occurs. Passive connectors are the origin of throttling notifications. Depending on the type
96 of connector (output or input) the respective throttling is called forward or backward
99 Passive connectors always handle two throttling states:
101 \li The \e native throttling state is set manually by the module. It is the throttling state
102 originating in the current module
103 \li The \e forwarded throttling state is the state as it is received by throttling
106 The accumulative throttling state is generated by combining all sub-states.
108 class PassiveConnector
109 : public virtual Connector
112 template <class Handler>
113 void onRequest(Handler handler);///< Register I/O event handler
114 /**< The registered handler will be called, whenever packets
115 arrive or should be generated by the module depending
116 on the connector type (input or output). The \a handler
117 argument is either an arbitrary callable object or it
118 is a pointer-to-member to a member of the class which
119 holds this input. In the second case, the pointer will
120 automatically be bound to the containing instance.
122 \param[in] handler Handler to call, whenever an I/O
123 operation is to be performed. */
126 bool throttled() const; ///< Get accumulative throttling state
127 bool nativeThrottled() const; ///< Get native throttling state
129 void throttle(); ///< Set native throttling
130 void unthrottle(); ///< Revoke native throttling
132 ActiveConnector & peer() const;
140 // Called by the routing to change the remote throttling state
141 void notifyThrottle(); ///< Forward a throttle notification to this connector
142 void notifyUnthrottle(); ///< Forward an unthrottle notification to this connector
144 // Internal members to emit throttling notifications
146 void emitUnthrottle();
148 // Called after unthrottling the connector
149 virtual void v_unthrottleEvent();
151 // called by ForwardingRoute to register a new route
152 void registerRoute(ForwardingRoute & route);
154 typedef detail::Callback<>::type Callback;
157 bool remoteThrottled_;
158 bool nativeThrottled_;
160 typedef std::vector<ForwardingRoute*> Routes;
163 friend class senf::ppi::ForwardingRoute;
166 /** \brief Active connector base-class
168 An active connector is a connector which emits I/O requests. Active connectors receive
169 throttling notifications. Depending on the type of connector (input or output) the
170 respective throttling is called forward or backward throttling.
172 Active connectors do not handle any throttling state, they just receive the
173 notifications. These notifications should then either be processed by the module or be
174 forwarded to other connectors.
176 class ActiveConnector
177 : public virtual Connector
179 typedef detail::Callback<>::type Callback;
181 template <class Handler>
182 void onThrottle(Handler handler); ///< Register throttle notification handler
183 /**< The handler register here will be called, whenever a
184 throttle notification comes in. The \a handler argument
185 is either an arbitrary callable object or it is a
186 pointer-to-member to a member of the class which holds
187 this input. In the second case, the pointer will
188 automatically be bound to the containing instance.
190 \param[in] handler Handler to call on throttle
192 void onThrottle(); ///< Clear throttle notification handler
194 template <class Handler>
195 void onUnthrottle(Handler handler); ///< Register unthrottle notification handler
196 /**< The handler register here will be called, whenever an
197 unthrottle notification comes in. The \a handler
198 argument is either an arbitrary callable object or it
199 is a pointer-to-member to a member of the class which
200 holds this input. In the second case, the pointer will
201 automatically be bound to the containing instance.
203 \param[in] handle Handler to call on unthrottle
205 void onUnthrottle(); ///< Clear unthrottle notification handler
207 bool throttled() const; ///< \c true, if peer() is throttled
209 PassiveConnector & peer() const;
215 // called by the peer() to forward throttling notifications
216 void notifyThrottle();
217 void notifyUnthrottle();
219 // called by ForwardingRoute to register a new route
220 void registerRoute(ForwardingRoute & route);
222 Callback throttleCallback_;
223 Callback unthrottleCallback_;
225 typedef std::vector<ForwardingRoute*> NotifyRoutes;
226 NotifyRoutes notifyRoutes_;
228 friend class senf::ppi::ForwardingRoute;
229 friend class PassiveConnector;
232 /** \brief Input connector base-class
234 An input connector receives packets. It may be either an ActiveConnector or a
235 PassiveConnector. An input connector contains a packet queue. This queue enables processing
236 packets in batches or generating multiple output packets from a single input packet. The
237 queues have the potential to greatly simplify the module implementations.
239 \implementation Which container to use?
240 \li list has good insertion and deletion properties on both ends but it costs a dynamic
241 memory allocation for every insertion. A very good property is, that iterators stay
242 valid across insertions/deletions
243 \li vector is fast and has good amortized dynamic allocation properties. However, it is
244 quite unusable as a queue
245 \li deque has comparable dynamic allocation properties as vector but also has good
246 insertion/removal properties on both ends.
248 So probably we will use a deque. I'd like a container which keeps iterators intact on
249 insertion/deletion but I believe that list is just to expensive since every packet will
250 be added to the queue before it can be processed.
253 : public virtual Connector
255 typedef std::deque<Packet> Queue;
257 typedef Queue::const_iterator queue_iterator; ///< Iterator type of the embedded queue
258 typedef Queue::size_type size_type; ///< Unsigned type for counting queue elements
260 Packet operator()(); ///< Get a packet
261 /**< This member is the primary method to access received
262 data. On passive connectors, this operator will just
263 dequeue a packet from the packet queue. If the
264 connector is active, the connector will request new
265 packets from the connected module. If the packet
266 request cannot be fulfilled, this is considered to be a
267 logic error in the module implementation and an
268 exception is raised. */
270 OutputConnector & peer() const;
272 queue_iterator begin() const; ///< Access queue begin (head)
273 queue_iterator end() const; ///< Access queue past-the-end (tail)
274 Packet peek() const; ///< Return head element from the queue
276 size_type queueSize() const; ///< Return number of elements in the queue
277 bool empty() const; ///< Return queueSize() == 0
283 void enqueue(Packet p);
285 virtual void v_requestEvent();
286 virtual void v_enqueueEvent();
287 virtual void v_dequeueEvent();
291 friend class OutputConnector;
294 /** \brief Output connector base-class
296 An output connector sends out packets. It may be either an ActiveConnector or a
297 PassiveConnector. An output connector does \e not have an built-in queueing, it relies on
298 the queueing of the connected input.
300 class OutputConnector
301 : public virtual Connector
304 void operator()(Packet p); ///< Send out a packet
306 InputConnector & peer() const;
313 ///\addtogroup connectors
315 /** \brief Combination of PassiveConnector and InputConnector
317 The PassiveInput automatically controls the connectors throttling state using a queueing
318 discipline. The standard queueing discipline is ThresholdQueueing, which throttles the
319 connection whenever the queue length reaches the high threshold and unthrottles the
320 connection when the queue reaches the low threshold. The default queueing discipline is
321 <tt>ThresholdQueueing(1,0)</tt> which will throttle the input whenever the queue is
325 : public PassiveConnector, public InputConnector,
326 public SafeBool<PassiveInput>
331 ActiveOutput & peer() const;
333 bool boolean_test() const; ///< \c true, if ! empty()
335 template <class QDisc>
336 void qdisc(QDisc const & disc); ///< Change the queueing discipline
337 /**< The queueing discipline is a class which provides the
338 QueueingDiscipline interface.
340 \param[in] disc New queueing discipline */
343 void v_enqueueEvent();
344 void v_dequeueEvent();
345 void v_unthrottleEvent();
347 boost::scoped_ptr<QueueingDiscipline> qdisc_;
350 /** \brief Combination of PassiveConnector and OutputConnector
353 : public PassiveConnector, public OutputConnector,
354 public SafeBool<PassiveOutput>
357 ActiveInput & peer() const;
359 bool boolean_test() const; ///< Always \c true
361 void connect(ActiveInput & target); ///< Internal: Use senf::ppi::connect() instead
363 friend class ActiveInput;
366 /** \brief Combination of ActiveConnector and InputConnector
369 : public ActiveConnector, public InputConnector,
370 public SafeBool<ActiveInput>
373 PassiveOutput & peer() const;
375 bool boolean_test() const; ///< \c true, if ! empty() or ! throttled()
377 void request(); ///< request more packets without dequeuing any packet
380 void v_requestEvent();
383 /** \brief Combination of ActiveConnector and OutputConnector
386 : public ActiveConnector, public OutputConnector,
387 public SafeBool<ActiveOutput>
390 PassiveInput & peer() const;
392 bool boolean_test() const; ///< \c true if peer() is ! throttled()
394 void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead
401 ///////////////////////////////hh.e////////////////////////////////////////
402 #include "Connectors.cci"
403 //#include "Connectors.ct"
404 #include "Connectors.cti"
411 // c-file-style: "senf"
412 // indent-tabs-mode: nil
413 // ispell-local-dictionary: "american"
414 // compile-command: "scons -u test"
415 // comment-column: 40