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 #ifndef HH_Connectors_
25 #define HH_Connectors_ 1
29 #include <boost/utility.hpp>
30 #include <boost/scoped_ptr.hpp>
31 #include "../Utils/SafeBool.hh"
32 #include "../Packets/Packets.hh"
34 #include "detail/Callback.hh"
35 #include "Queueing.hh"
37 //#include "Connectors.mpp"
38 ///////////////////////////////hh.p////////////////////////////////////////
44 /** \namespace senf::ppi::connector
45 \brief Connector classes
47 A connector has two independent properties
48 \li it may be \e active or \e passive
49 \li it may be an \e input or an \e output
51 \e Active connectors are activated from within the module, \e passive connectors are
52 signaled by the external framework. \e Input modules receive packets, \e output modules send
55 All passive connectors call some onRequest callback whenever I/O needs to be performed. All
56 input modules possess a packet queue.
58 We therefore have 4 connector types: senf::ppi::ActiveInput, senf::ppi::ActiveOutput,
59 senf::ppi::PassiveInput and senf::ppi::PassiveOutput.
62 /** \brief Connector base-class
64 This connector provides access to the generic connector facilities. This includes the
65 connection management (access to the connected peer) and the containment management (access
66 to the containing module)
72 Connector & peer() const; ///< Get peer connected to this connector
73 module::Module & module() const; ///< Get this connectors containing module
79 void connect(Connector & target);
82 void setModule(module::Module & module);
85 module::Module * module_;
87 friend class module::Module;
90 /** \brief Passive connector base-class
92 A passive connector is a connector which is activated externally whenever an I/O request
93 occurs. Passive connectors are the origin of throttling notifications. Depending on the type
94 of connector (output or input) the respective throttling is called forward or backward
97 Passive connectors always handle two throttling states:
99 \li The \e native throttling state is set manually by the module. It is the throttling state
100 originating in the current module
101 \li The \e forwarded throttling state is the state as it is received by throttling
104 The accumulative throttling state is generated by combining all sub-states.
106 class PassiveConnector
107 : public virtual Connector
110 template <class Handler>
111 void onRequest(Handler handler);///< Register I/O event handler
112 /**< The registered handler will be called, whenever packets
113 arrive or should be generated by the module depending
114 on the connector type (input or output). The \a handler
115 argument is either an arbitrary callable object or it
116 is a pointer-to-member to a member of the class which
117 holds this input. In the second case, the pointer will
118 automatically be bound to the containing instance.
120 \param[in] handler Handler to call, whenever an I/O
121 operation is to be performed. */
124 bool throttled() const; ///< Get accumulative throttling state
125 bool nativeThrottled() const; ///< Get native throttling state
127 void throttle(); ///< Set native throttling
128 void unthrottle(); ///< Revoke native throttling
130 ActiveConnector & peer() const;
138 // Called by the routing to change the remote throttling state
139 void notifyThrottle(); ///< Forward a throttle notification to this connector
140 void notifyUnthrottle(); ///< Forward an unthrottle notification to this connector
142 // Internal members to emit throttling notifications
144 void emitUnthrottle();
146 // Called after unthrottling the connector
147 virtual void v_unthrottleEvent();
149 // called by ForwardingRoute to register a new route
150 void registerRoute(ForwardingRoute & route);
152 typedef detail::Callback<>::type Callback;
155 bool remoteThrottled_;
156 bool nativeThrottled_;
158 typedef std::vector<ForwardingRoute*> Routes;
161 friend class senf::ppi::ForwardingRoute;
164 /** \brief Active connector base-class
166 An active connector is a connector which emits I/O requests. Active connectors receive
167 throttling notifications. Depending on the type of connector (input or output) the
168 respective throttling is called forward or backward throttling.
170 Active connectors do not handle any throttling state, they just receive the
171 notifications. These notifications should then either be processed by the module or be
172 forwarded to other connectors.
174 class ActiveConnector
175 : public virtual Connector
177 typedef detail::Callback<>::type Callback;
179 template <class Handler>
180 void onThrottle(Handler handler); ///< Register throttle notification handler
181 /**< The handler register here will be called, whenever a
182 throttle notification comes in. The \a handler argument
183 is either an arbitrary callable object or it is a
184 pointer-to-member to a member of the class which holds
185 this input. In the second case, the pointer will
186 automatically be bound to the containing instance.
188 \param[in] handler Handler to call on throttle
190 void onThrottle(); ///< Clear throttle notification handler
192 template <class Handler>
193 void onUnthrottle(Handler handler); ///< Register unthrottle notification handler
194 /**< The handler register here will be called, whenever an
195 unthrottle notification comes in. The \a handler
196 argument is either an arbitrary callable object or it
197 is a pointer-to-member to a member of the class which
198 holds this input. In the second case, the pointer will
199 automatically be bound to the containing instance.
201 \param[in] handler Handler to call on unthrottle
203 void onUnthrottle(); ///< Clear unthrottle notification handler
205 bool throttled() const; ///< \c true, if peer() is throttled
207 PassiveConnector & peer() const;
213 // called by the peer() to forward throttling notifications
214 void notifyThrottle();
215 void notifyUnthrottle();
217 // called by ForwardingRoute to register a new route
218 void registerRoute(ForwardingRoute & route);
220 Callback throttleCallback_;
221 Callback unthrottleCallback_;
223 typedef std::vector<ForwardingRoute*> NotifyRoutes;
224 NotifyRoutes notifyRoutes_;
226 friend class senf::ppi::ForwardingRoute;
227 friend class PassiveConnector;
230 /** \brief Input connector base-class
232 An input connector receives packets. It may be either an ActiveConnector or a
233 PassiveConnector. An input connector contains a packet queue. This queue enables processing
234 packets in batches or generating multiple output packets from a single input packet. The
235 queues have the potential to greatly simplify the module implementations.
237 \implementation Which container to use?
238 \li list has good insertion and deletion properties on both ends but it costs a dynamic
239 memory allocation for every insertion. A very good property is, that iterators stay
240 valid across insertions/deletions
241 \li vector is fast and has good amortized dynamic allocation properties. However, it is
242 quite unusable as a queue
243 \li deque has comparable dynamic allocation properties as vector but also has good
244 insertion/removal properties on both ends.
246 So probably we will use a deque. I'd like a container which keeps iterators intact on
247 insertion/deletion but I believe that list is just to expensive since every packet will
248 be added to the queue before it can be processed.
251 : public virtual Connector
253 typedef std::deque<Packet> Queue;
255 typedef Queue::const_iterator queue_iterator; ///< Iterator type of the embedded queue
256 typedef Queue::size_type size_type; ///< Unsigned type for counting queue elements
259 Packet operator()(); ///< Get a packet
260 /**< This member is the primary method to access received
261 data. On passive connectors, this operator will just
262 dequeue a packet from the packet queue. If the
263 connector is active, the connector will request new
264 packets from the connected module. If the packet
265 request cannot be fulfilled, this is considered to be a
266 logic error in the module implementation and an
267 exception is raised. */
269 Packet read(); ///< Alias for \ref operator()()
271 OutputConnector & peer() const;
273 queue_iterator begin() const; ///< Access queue begin (head)
274 queue_iterator end() const; ///< Access queue past-the-end (tail)
275 Packet peek() const; ///< Return head element from the queue
277 size_type queueSize() const; ///< Return number of elements in the queue
278 bool empty() const; ///< Return queueSize() == 0
284 void enqueue(Packet p);
286 virtual void v_requestEvent();
287 virtual void v_enqueueEvent();
288 virtual void v_dequeueEvent();
292 friend class OutputConnector;
295 /** \brief Output connector base-class
297 An output connector sends out packets. It may be either an ActiveConnector or a
298 PassiveConnector. An output connector does \e not have an built-in queueing, it relies on
299 the queueing of the connected input.
301 class OutputConnector
302 : public virtual Connector
305 void operator()(Packet p); ///< Send out a packet
307 void write(Packet p); ///< Alias for \ref operator()()
309 InputConnector & peer() const;
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
399 ///////////////////////////////hh.e////////////////////////////////////////
400 #include "Connectors.cci"
401 //#include "Connectors.ct"
402 #include "Connectors.cti"
409 // c-file-style: "senf"
410 // indent-tabs-mode: nil
411 // ispell-local-dictionary: "american"
412 // compile-command: "scons -u test"
413 // comment-column: 40