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] handle 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
258 Packet operator()(); ///< Get a packet
259 /**< This member is the primary method to access received
260 data. On passive connectors, this operator will just
261 dequeue a packet from the packet queue. If the
262 connector is active, the connector will request new
263 packets from the connected module. If the packet
264 request cannot be fulfilled, this is considered to be a
265 logic error in the module implementation and an
266 exception is raised. */
268 OutputConnector & peer() const;
270 queue_iterator begin() const; ///< Access queue begin (head)
271 queue_iterator end() const; ///< Access queue past-the-end (tail)
272 Packet peek() const; ///< Return head element from the queue
274 size_type queueSize() const; ///< Return number of elements in the queue
275 bool empty() const; ///< Return queueSize() == 0
281 void enqueue(Packet p);
283 virtual void v_requestEvent();
284 virtual void v_enqueueEvent();
285 virtual void v_dequeueEvent();
289 friend class OutputConnector;
292 /** \brief Output connector base-class
294 An output connector sends out packets. It may be either an ActiveConnector or a
295 PassiveConnector. An output connector does \e not have an built-in queueing, it relies on
296 the queueing of the connected input.
298 class OutputConnector
299 : public virtual Connector
302 void operator()(Packet p); ///< Send out a packet
304 InputConnector & peer() const;
310 /** \brief Combination of PassiveConnector and InputConnector
312 The PassiveInput automatically controls the connectors throttling state using a queueing
313 discipline. The standard queueing discipline is ThresholdQueueing, which throttles the
314 connection whenever the queue length reaches the high threshold and unthrottles the
315 connection when the queue reaches the low threshold. The default queueing discipline is
316 <tt>ThresholdQueueing(1,0)</tt> which will throttle the input whenever the queue is
320 : public PassiveConnector, public InputConnector,
321 public SafeBool<PassiveInput>
326 ActiveOutput & peer() const;
328 bool boolean_test() const; ///< \c true, if ! empty()
330 template <class QDisc>
331 void qdisc(QDisc const & disc); ///< Change the queueing discipline
332 /**< The queueing discipline is a class which provides the
333 QueueingDiscipline interface.
335 \param[in] disc New queueing discipline */
338 void v_enqueueEvent();
339 void v_dequeueEvent();
340 void v_unthrottleEvent();
342 boost::scoped_ptr<QueueingDiscipline> qdisc_;
345 /** \brief Combination of PassiveConnector and OutputConnector
348 : public PassiveConnector, public OutputConnector,
349 public SafeBool<PassiveOutput>
352 ActiveInput & peer() const;
354 bool boolean_test() const; ///< Always \c true
356 void connect(ActiveInput & target); ///< Internal: Use senf::ppi::connect() instead
358 friend class ActiveInput;
361 /** \brief Combination of ActiveConnector and InputConnector
364 : public ActiveConnector, public InputConnector,
365 public SafeBool<ActiveInput>
368 PassiveOutput & peer() const;
370 bool boolean_test() const; ///< \c true, if ! empty() or ! throttled()
372 void request(); ///< request more packets without dequeuing any packet
375 void v_requestEvent();
378 /** \brief Combination of ActiveConnector and OutputConnector
381 : public ActiveConnector, public OutputConnector,
382 public SafeBool<ActiveOutput>
385 PassiveInput & peer() const;
387 bool boolean_test() const; ///< \c true if peer() is ! throttled()
389 void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead
394 ///////////////////////////////hh.e////////////////////////////////////////
395 #include "Connectors.cci"
396 //#include "Connectors.ct"
397 #include "Connectors.cti"
404 // c-file-style: "senf"
405 // indent-tabs-mode: nil
406 // ispell-local-dictionary: "american"
407 // compile-command: "scons -u test"
408 // comment-column: 40