4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Connectors public header */
26 #ifndef HH_Connectors_
27 #define HH_Connectors_ 1
31 #include <boost/utility.hpp>
32 #include <boost/scoped_ptr.hpp>
33 #include "../Utils/safe_bool.hh"
34 #include "../Packets/Packets.hh"
36 #include "detail/Callback.hh"
37 #include "Queueing.hh"
39 //#include "Connectors.mpp"
40 ///////////////////////////////hh.p////////////////////////////////////////
46 /** \namespace senf::ppi::connector
47 \brief Connector classes
49 A connector has two independent properties
50 \li it may be \e active or \e passive
51 \li it may be an \e input or an \e output
53 \e Active connectors are activated from within the module, \e passive connectors are
54 signaled by the external framework. \e Input modules receive packets, \e output modules send
57 All passive connectors call some onRequest callback whenever I/O needs to be performed. All
58 input modules possess a packet queue.
60 We therefore have 4 connector types:
61 \li senf::ppi::connector::ActiveInput
62 \li senf::ppi::connector::ActiveOutput
63 \li senf::ppi::connector::PassiveInput
64 \li senf::ppi::connector::PassiveOutput.
66 Connectors are declared as module data members and are then externally connected to other
70 senf::ppi::module::Module \n
75 /** \brief Connector base-class
77 This connector provides access to the generic connector facilities. This includes the
78 connection management (access to the connected peer) and the containment management (access
79 to the containing module)
85 Connector & peer() const; ///< Get peer connected to this connector
86 module::Module & module() const; ///< Get this connectors containing module
92 void connect(Connector & target);
95 void setModule(module::Module & module);
98 module::Module * module_;
100 friend class module::Module;
103 /** \brief Passive connector base-class
105 A passive connector is a connector which is activated externally whenever an I/O request
106 occurs. Passive connectors are the origin of throttling notifications. Depending on the type
107 of connector (output or input) the respective throttling is called forward or backward
110 Passive connectors always handle two throttling states:
112 \li The \e native throttling state is set manually by the module. It is the throttling state
113 originating in the current module
114 \li The \e forwarded throttling state is the state as it is received by throttling
117 The accumulative throttling state is generated by combining all sub-states.
119 class PassiveConnector
120 : public virtual Connector
123 template <class Handler>
124 void onRequest(Handler handler);///< Register I/O event handler
125 /**< The registered handler will be called, whenever packets
126 arrive or should be generated by the module depending
127 on the connector type (input or output). The \a handler
128 argument is either an arbitrary callable object or it
129 is a pointer-to-member to a member of the class which
130 holds this input. In the second case, the pointer will
131 automatically be bound to the containing instance.
133 \param[in] handler Handler to call, whenever an I/O
134 operation is to be performed. */
137 bool throttled() const; ///< Get accumulative throttling state
138 bool nativeThrottled() const; ///< Get native throttling state
140 void throttle(); ///< Set native throttling
141 void unthrottle(); ///< Revoke native throttling
143 ActiveConnector & peer() const;
151 // Called by the routing to change the remote throttling state
152 void notifyThrottle(); ///< Forward a throttle notification to this connector
153 void notifyUnthrottle(); ///< Forward an unthrottle notification to this connector
155 // Internal members to emit throttling notifications
157 void emitUnthrottle();
159 // Called after unthrottling the connector
160 virtual void v_unthrottleEvent();
162 // called by ForwardingRoute to register a new route
163 void registerRoute(ForwardingRoute & route);
165 typedef detail::Callback<>::type Callback;
168 bool remoteThrottled_;
169 bool nativeThrottled_;
171 typedef std::vector<ForwardingRoute*> Routes;
174 friend class senf::ppi::ForwardingRoute;
177 /** \brief Active connector base-class
179 An active connector is a connector which emits I/O requests. Active connectors receive
180 throttling notifications. Depending on the type of connector (input or output) the
181 respective throttling is called forward or backward throttling.
183 Active connectors do not handle any throttling state, they just receive the
184 notifications. These notifications should then either be processed by the module or be
185 forwarded to other connectors.
187 class ActiveConnector
188 : public virtual Connector
190 typedef detail::Callback<>::type Callback;
192 template <class Handler>
193 void onThrottle(Handler handler); ///< Register throttle notification handler
194 /**< The handler register here will be called, whenever a
195 throttle notification comes in. The \a handler argument
196 is either an arbitrary callable object or it is a
197 pointer-to-member to a member of the class which holds
198 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 throttle
203 void onThrottle(); ///< Clear throttle notification handler
205 template <class Handler>
206 void onUnthrottle(Handler handler); ///< Register unthrottle notification handler
207 /**< The handler register here will be called, whenever an
208 unthrottle notification comes in. The \a handler
209 argument is either an arbitrary callable object or it
210 is a pointer-to-member to a member of the class which
211 holds this input. In the second case, the pointer will
212 automatically be bound to the containing instance.
214 \param[in] handler Handler to call on unthrottle
216 void onUnthrottle(); ///< Clear unthrottle notification handler
218 bool throttled() const; ///< \c true, if peer() is throttled
220 PassiveConnector & peer() const;
226 // called by the peer() to forward throttling notifications
227 void notifyThrottle();
228 void notifyUnthrottle();
230 // called by ForwardingRoute to register a new route
231 void registerRoute(ForwardingRoute & route);
233 Callback throttleCallback_;
234 Callback unthrottleCallback_;
236 typedef std::vector<ForwardingRoute*> NotifyRoutes;
237 NotifyRoutes notifyRoutes_;
239 friend class senf::ppi::ForwardingRoute;
240 friend class PassiveConnector;
243 /** \brief Input connector base-class
245 An input connector receives packets. It may be either an ActiveConnector or a
246 PassiveConnector. An input connector contains a packet queue. This queue enables processing
247 packets in batches or generating multiple output packets from a single input packet. The
248 queues have the potential to greatly simplify the module implementations.
250 \implementation Which container to use?
251 \li list has good insertion and deletion properties on both ends but it costs a dynamic
252 memory allocation for every insertion. A very good property is, that iterators stay
253 valid across insertions/deletions
254 \li vector is fast and has good amortized dynamic allocation properties. However, it is
255 quite unusable as a queue
256 \li deque has comparable dynamic allocation properties as vector but also has good
257 insertion/removal properties on both ends.
259 So probably we will use a deque. I'd like a container which keeps iterators intact on
260 insertion/deletion but I believe that list is just to expensive since every packet will
261 be added to the queue before it can be processed.
264 : public virtual Connector
266 typedef std::deque<Packet> Queue;
268 typedef Queue::const_iterator queue_iterator; ///< Iterator type of the embedded queue
269 typedef Queue::size_type size_type; ///< Unsigned type for counting queue elements
272 Packet operator()(); ///< Get a packet
273 /**< This member is the primary method to access received
274 data. On passive connectors, this operator will just
275 dequeue a packet from the packet queue. If the
276 connector is active, the connector will request new
277 packets from the connected module. If the packet
278 request cannot be fulfilled, this is considered to be a
279 logic error in the module implementation and an
280 exception is raised. */
282 Packet read(); ///< Alias for operator()()
284 OutputConnector & peer() const;
286 queue_iterator begin() const; ///< Access queue begin (head)
287 queue_iterator end() const; ///< Access queue past-the-end (tail)
288 Packet peek() const; ///< Return head element from the queue
290 size_type queueSize() const; ///< Return number of elements in the queue
291 bool empty() const; ///< Return queueSize() == 0
297 void enqueue(Packet p);
299 virtual void v_requestEvent();
300 virtual void v_enqueueEvent();
301 virtual void v_dequeueEvent();
305 friend class OutputConnector;
308 /** \brief Output connector base-class
310 An output connector sends out packets. It may be either an ActiveConnector or a
311 PassiveConnector. An output connector does \e not have an built-in queueing, it relies on
312 the queueing of the connected input.
314 class OutputConnector
315 : public virtual Connector
318 void operator()(Packet p); ///< Send out a packet
320 void write(Packet p); ///< Alias for operator()(Packet p)
322 InputConnector & peer() const;
328 /** \brief Combination of PassiveConnector and InputConnector
330 The PassiveInput automatically controls the connectors throttling state using a queueing
331 discipline. The standard queueing discipline is ThresholdQueueing, which throttles the
332 connection whenever the queue length reaches the high threshold and unthrottles the
333 connection when the queue reaches the low threshold. The default queueing discipline is
334 <tt>ThresholdQueueing(1,0)</tt> which will throttle the input whenever the queue is
338 : public PassiveConnector, public InputConnector,
339 public safe_bool<PassiveInput>
344 ActiveOutput & peer() const;
346 bool boolean_test() const; ///< \c true, if ! empty()
348 template <class QDisc>
349 void qdisc(QDisc const & disc); ///< Change the queueing discipline
350 /**< The queueing discipline is a class which provides the
351 QueueingDiscipline interface.
353 \param[in] disc New queueing discipline */
356 void v_enqueueEvent();
357 void v_dequeueEvent();
358 void v_unthrottleEvent();
360 boost::scoped_ptr<QueueingDiscipline> qdisc_;
363 /** \brief Combination of PassiveConnector and OutputConnector
366 : public PassiveConnector, public OutputConnector,
367 public safe_bool<PassiveOutput>
370 ActiveInput & peer() const;
372 bool boolean_test() const; ///< Always \c true
374 void connect(ActiveInput & target); ///< Internal: Use senf::ppi::connect() instead
376 friend class ActiveInput;
379 /** \brief Combination of ActiveConnector and InputConnector
382 : public ActiveConnector, public InputConnector,
383 public safe_bool<ActiveInput>
386 PassiveOutput & peer() const;
388 bool boolean_test() const; ///< \c true, if ! empty() or ! throttled()
390 void request(); ///< request more packets without dequeuing any packet
393 void v_requestEvent();
396 /** \brief Combination of ActiveConnector and OutputConnector
399 : public ActiveConnector, public OutputConnector,
400 public safe_bool<ActiveOutput>
403 PassiveInput & peer() const;
405 bool boolean_test() const; ///< \c true if peer() is ! throttled()
407 void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead
412 ///////////////////////////////hh.e////////////////////////////////////////
413 #include "Connectors.cci"
414 //#include "Connectors.ct"
415 #include "Connectors.cti"
422 // c-file-style: "senf"
423 // indent-tabs-mode: nil
424 // ispell-local-dictionary: "american"
425 // compile-command: "scons -u test"
426 // comment-column: 40