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/safe_bool.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:
59 \li senf::ppi::connector::ActiveInput
60 \li senf::ppi::connector::ActiveOutput
61 \li senf::ppi::connector::PassiveInput
62 \li senf::ppi::connector::PassiveOutput.
64 Connectors are declared as module data members and are then externally connected to other
68 senf::ppi::module::Module \n
73 /** \brief Connector base-class
75 This connector provides access to the generic connector facilities. This includes the
76 connection management (access to the connected peer) and the containment management (access
77 to the containing module)
83 Connector & peer() const; ///< Get peer connected to this connector
84 module::Module & module() const; ///< Get this connectors containing module
90 void connect(Connector & target);
93 void setModule(module::Module & module);
96 module::Module * module_;
98 friend class module::Module;
101 /** \brief Passive connector base-class
103 A passive connector is a connector which is activated externally whenever an I/O request
104 occurs. Passive connectors are the origin of throttling notifications. Depending on the type
105 of connector (output or input) the respective throttling is called forward or backward
108 Passive connectors always handle two throttling states:
110 \li The \e native throttling state is set manually by the module. It is the throttling state
111 originating in the current module
112 \li The \e forwarded throttling state is the state as it is received by throttling
115 The accumulative throttling state is generated by combining all sub-states.
117 class PassiveConnector
118 : public virtual Connector
121 template <class Handler>
122 void onRequest(Handler handler);///< Register I/O event handler
123 /**< The registered handler will be called, whenever packets
124 arrive or should be generated by the module depending
125 on the connector type (input or output). The \a handler
126 argument is either an arbitrary callable object or it
127 is a pointer-to-member to a member of the class which
128 holds this input. In the second case, the pointer will
129 automatically be bound to the containing instance.
131 \param[in] handler Handler to call, whenever an I/O
132 operation is to be performed. */
135 bool throttled() const; ///< Get accumulative throttling state
136 bool nativeThrottled() const; ///< Get native throttling state
138 void throttle(); ///< Set native throttling
139 void unthrottle(); ///< Revoke native throttling
141 ActiveConnector & peer() const;
149 // Called by the routing to change the remote throttling state
150 void notifyThrottle(); ///< Forward a throttle notification to this connector
151 void notifyUnthrottle(); ///< Forward an unthrottle notification to this connector
153 // Internal members to emit throttling notifications
155 void emitUnthrottle();
157 // Called after unthrottling the connector
158 virtual void v_unthrottleEvent();
160 // called by ForwardingRoute to register a new route
161 void registerRoute(ForwardingRoute & route);
163 typedef detail::Callback<>::type Callback;
166 bool remoteThrottled_;
167 bool nativeThrottled_;
169 typedef std::vector<ForwardingRoute*> Routes;
172 friend class senf::ppi::ForwardingRoute;
175 /** \brief Active connector base-class
177 An active connector is a connector which emits I/O requests. Active connectors receive
178 throttling notifications. Depending on the type of connector (input or output) the
179 respective throttling is called forward or backward throttling.
181 Active connectors do not handle any throttling state, they just receive the
182 notifications. These notifications should then either be processed by the module or be
183 forwarded to other connectors.
185 class ActiveConnector
186 : public virtual Connector
188 typedef detail::Callback<>::type Callback;
190 template <class Handler>
191 void onThrottle(Handler handler); ///< Register throttle notification handler
192 /**< The handler register here will be called, whenever a
193 throttle notification comes in. The \a handler argument
194 is either an arbitrary callable object or it is a
195 pointer-to-member to a member of the class which holds
196 this input. In the second case, the pointer will
197 automatically be bound to the containing instance.
199 \param[in] handler Handler to call on throttle
201 void onThrottle(); ///< Clear throttle notification handler
203 template <class Handler>
204 void onUnthrottle(Handler handler); ///< Register unthrottle notification handler
205 /**< The handler register here will be called, whenever an
206 unthrottle notification comes in. The \a handler
207 argument is either an arbitrary callable object or it
208 is a pointer-to-member to a member of the class which
209 holds this input. In the second case, the pointer will
210 automatically be bound to the containing instance.
212 \param[in] handler Handler to call on unthrottle
214 void onUnthrottle(); ///< Clear unthrottle notification handler
216 bool throttled() const; ///< \c true, if peer() is throttled
218 PassiveConnector & peer() const;
224 // called by the peer() to forward throttling notifications
225 void notifyThrottle();
226 void notifyUnthrottle();
228 // called by ForwardingRoute to register a new route
229 void registerRoute(ForwardingRoute & route);
231 Callback throttleCallback_;
232 Callback unthrottleCallback_;
234 typedef std::vector<ForwardingRoute*> NotifyRoutes;
235 NotifyRoutes notifyRoutes_;
237 friend class senf::ppi::ForwardingRoute;
238 friend class PassiveConnector;
241 /** \brief Input connector base-class
243 An input connector receives packets. It may be either an ActiveConnector or a
244 PassiveConnector. An input connector contains a packet queue. This queue enables processing
245 packets in batches or generating multiple output packets from a single input packet. The
246 queues have the potential to greatly simplify the module implementations.
248 \implementation Which container to use?
249 \li list has good insertion and deletion properties on both ends but it costs a dynamic
250 memory allocation for every insertion. A very good property is, that iterators stay
251 valid across insertions/deletions
252 \li vector is fast and has good amortized dynamic allocation properties. However, it is
253 quite unusable as a queue
254 \li deque has comparable dynamic allocation properties as vector but also has good
255 insertion/removal properties on both ends.
257 So probably we will use a deque. I'd like a container which keeps iterators intact on
258 insertion/deletion but I believe that list is just to expensive since every packet will
259 be added to the queue before it can be processed.
262 : public virtual Connector
264 typedef std::deque<Packet> Queue;
266 typedef Queue::const_iterator queue_iterator; ///< Iterator type of the embedded queue
267 typedef Queue::size_type size_type; ///< Unsigned type for counting queue elements
270 Packet operator()(); ///< Get a packet
271 /**< This member is the primary method to access received
272 data. On passive connectors, this operator will just
273 dequeue a packet from the packet queue. If the
274 connector is active, the connector will request new
275 packets from the connected module. If the packet
276 request cannot be fulfilled, this is considered to be a
277 logic error in the module implementation and an
278 exception is raised. */
280 Packet read(); ///< Alias for operator()()
282 OutputConnector & peer() const;
284 queue_iterator begin() const; ///< Access queue begin (head)
285 queue_iterator end() const; ///< Access queue past-the-end (tail)
286 Packet peek() const; ///< Return head element from the queue
288 size_type queueSize() const; ///< Return number of elements in the queue
289 bool empty() const; ///< Return queueSize() == 0
295 void enqueue(Packet p);
297 virtual void v_requestEvent();
298 virtual void v_enqueueEvent();
299 virtual void v_dequeueEvent();
303 friend class OutputConnector;
306 /** \brief Output connector base-class
308 An output connector sends out packets. It may be either an ActiveConnector or a
309 PassiveConnector. An output connector does \e not have an built-in queueing, it relies on
310 the queueing of the connected input.
312 class OutputConnector
313 : public virtual Connector
316 void operator()(Packet p); ///< Send out a packet
318 void write(Packet p); ///< Alias for operator()(Packet p)
320 InputConnector & peer() const;
326 /** \brief Combination of PassiveConnector and InputConnector
328 The PassiveInput automatically controls the connectors throttling state using a queueing
329 discipline. The standard queueing discipline is ThresholdQueueing, which throttles the
330 connection whenever the queue length reaches the high threshold and unthrottles the
331 connection when the queue reaches the low threshold. The default queueing discipline is
332 <tt>ThresholdQueueing(1,0)</tt> which will throttle the input whenever the queue is
336 : public PassiveConnector, public InputConnector,
337 public safe_bool<PassiveInput>
342 ActiveOutput & peer() const;
344 bool boolean_test() const; ///< \c true, if ! empty()
346 template <class QDisc>
347 void qdisc(QDisc const & disc); ///< Change the queueing discipline
348 /**< The queueing discipline is a class which provides the
349 QueueingDiscipline interface.
351 \param[in] disc New queueing discipline */
354 void v_enqueueEvent();
355 void v_dequeueEvent();
356 void v_unthrottleEvent();
358 boost::scoped_ptr<QueueingDiscipline> qdisc_;
361 /** \brief Combination of PassiveConnector and OutputConnector
364 : public PassiveConnector, public OutputConnector,
365 public safe_bool<PassiveOutput>
368 ActiveInput & peer() const;
370 bool boolean_test() const; ///< Always \c true
372 void connect(ActiveInput & target); ///< Internal: Use senf::ppi::connect() instead
374 friend class ActiveInput;
377 /** \brief Combination of ActiveConnector and InputConnector
380 : public ActiveConnector, public InputConnector,
381 public safe_bool<ActiveInput>
384 PassiveOutput & peer() const;
386 bool boolean_test() const; ///< \c true, if ! empty() or ! throttled()
388 void request(); ///< request more packets without dequeuing any packet
391 void v_requestEvent();
394 /** \brief Combination of ActiveConnector and OutputConnector
397 : public ActiveConnector, public OutputConnector,
398 public safe_bool<ActiveOutput>
401 PassiveInput & peer() const;
403 bool boolean_test() const; ///< \c true if peer() is ! throttled()
405 void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead
410 ///////////////////////////////hh.e////////////////////////////////////////
411 #include "Connectors.cci"
412 //#include "Connectors.ct"
413 #include "Connectors.cti"
420 // c-file-style: "senf"
421 // indent-tabs-mode: nil
422 // ispell-local-dictionary: "american"
423 // compile-command: "scons -u test"
424 // comment-column: 40