Add new file-variable 'comment-column'
[senf.git] / PPI / Connectors.hh
1 // Copyright (C) 2007 
2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 //     Stefan Bund <g0dil@berlios.de>
5 //
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.
10 //
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.
15 //
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.
20
21 /** \file
22     \brief Conenctors public header */
23
24 /** \defgroup connectors Connector classes
25
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
29     
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.
32
33     All passive connectors call some onRequest callback whenever I/O needs to be performed. All
34     input modules possess a packet queue.
35
36     We therefore have 4 connector types: senf::ppi::ActiveInput, senf::ppi::ActiveOutput,
37     senf::ppi::PassiveInput and senf::ppi::PassiveOutput.
38  */
39
40 #ifndef HH_Conenctors_
41 #define HH_Conenctors_ 1
42
43 // Custom includes
44 #include <boost/utility.hpp>
45
46 //#include "Conenctors.mpp"
47 ///////////////////////////////hh.p////////////////////////////////////////
48
49 namespace senf {
50 namespace ppi {
51 namespace connector {
52
53     /** \brief Connector baseclass
54
55         This connector provides access to the generic connector facilities. This includes the
56         connection management (access to the connected peer) and the containment management (access
57         to the containing module)
58      */
59     class Connector
60         : boost::noncopyable
61     {
62     public:
63         Connector & peer();             ///< Get peer connected to this connector
64         Module & module();              ///< Get this connectors containing module
65
66     protected:
67         // here to protect
68         Connector();
69         ~Connector();
70     };
71
72     /** \brief Passive connector baseclass
73
74         A passive connector is a connector which is activated externally whenever an I/O request
75         occurs. Passive connectors are the origin of throttling notifications. Depending on the type
76         of connector (output or input) the respective throttling is called forward or backward
77         throttling.
78
79         Passive connectors always handle two throttling states: 
80         
81         \li The \e native throttling state is set manually by the module. It is the throttling state
82             originating in the current module
83         \li The \e forwarded throttling state is the state as it is received by throttling
84             notifications
85
86         The accumulative throttling state is generated by combining all sub-states.
87      */
88     class PassiveConnector 
89         : public virtual Connector
90     {
91     public:
92         template <class Handler>
93         void onRequest(Handler handler);///< Register I/O event handler
94                                         /**< The registered handler will be called, whenever packets
95                                              arrive or should be generated by the module depending
96                                              on the connector type (input or output). The \a handler
97                                              argument is either an arbitrary callable object or it
98                                              is a pointer-to-member to a member of the class which
99                                              holds this input. In the second case, the pointer will
100                                              automatically be bound to the containing instance.
101                                              
102                                              \param[in] handler Handler to call, whenever an I/O
103                                                  operation is to be performed. */
104
105         
106         bool throttled();               ///< Get accumulative throttling state
107         bool nativeThrottled();         ///< Get native throttling state
108
109         void throttle();                ///< Set native throttling
110         void unthrottle();              ///< Revoke native throttling
111         
112         void notifyThrottle();          ///< Forward a throttling notification to this connector
113         void notifyUnthrottle();        ///< Forward an unthrottling notification to this connector
114
115         ActiveConnector & peer();
116
117     protected:
118         // here to protect
119         PassiveConnector();
120         ~PassiveConnector();
121     };
122
123     /** \brief Active connector baseclass
124
125         An active connector is a connector which emits I/O requests. Active connectors receive
126         throttling notifications. Depending on the type of connector (input or output) the
127         respective throttling is called forward or backward throttling.
128
129         Active connectors do not handle any throttling state, they just receive the
130         notifications. These notifications should then either be processed by the module or be
131         forwarded to other connectors.
132      */
133     class ActiveConnector 
134         : public virtual Connector
135     {
136     public:
137         template <class Handler>
138         void onThrottle(Handler handle); ///< Register throttle notification handler
139                                         /**< The handler register here will be called, whenever a
140                                              throttle notification comes in. The \a handler argument
141                                              is either an arbitrary callable object or it is a
142                                              pointer-to-member to a member of the class which holds
143                                              this input. In the second case, the pointer will
144                                              automatically be bound to the containing instance.
145
146                                              \param[in] handle Handler to call on throttle
147                                                  notifications. */
148
149         template <class Handler>
150         void onUnthrottle(Handler handle); ///< Register unthrottle notification handler
151                                         /**< The handler register here will be called, whenever an
152                                              unthrottle notification comes in. The \a handler
153                                              argument is either an arbitrary callable object or it
154                                              is a pointer-to-member to a member of the class which
155                                              holds this input. In the second case, the pointer will
156                                              automatically be bound to the containing instance.
157
158                                              \param[in] handle Handler to call on unthrottle
159                                                  notifications. */
160
161         PassiveConnector & peer();
162
163     protected:
164         // here to protect
165         PassiveConnector();
166         ~PassiveConnector();
167     };
168
169     /** \brief Input connector baseclass
170
171         An input connector receives packets. It may be either an ActiveConnector or a
172         PassiveConnector. An input connector contains a packet queue. This queue enables processing
173         packets in batches or generating multiple output packets from a single input packet. The
174         queues have the potential to greatly simplify the module implementations.
175
176         \implementation Which container to use?
177             \li list has good insertion and deletion properties on both ends but it costs a dynamic
178                 memory allocation for every insertion. A very good property is, that iterators stay
179                 valid across insertions/deletions
180             \li vector is fast and has good amortized dynamic allocation properties. However, it is
181                 quite unusable as a queue
182             \li deque has comparable dynamic allocation properties as vector but also has good
183                 insertion/removal properties on both ends.
184
185             So probably we will use a deque. I'd like a container which keeps iterators intact on
186             isertion/deletion but I believe that list is just to expensive since every packet will
187             be added to the queue before it can be processed.
188      */
189     class InputConnector 
190         : public virtual Connector
191     {
192     public:
193         typedef unspecified queue_iterator; ///< Iterator type of the embedded queue
194         typedef unspecified size_type;  ///< Unsigned type representing the number of queue elements
195
196         Packet::ptr operator();         ///< Get a packet
197                                         /**< This member is the primary method to access received
198                                              data. On passive connectors, this operator will just
199                                              dequeue a packet from the packet queue. If the
200                                              connector is active, the connector will request new
201                                              packets from the connected module. If the packet
202                                              request cannot be fulfilled, this is considered to be a
203                                              logic error in the module implementation and an
204                                              exception is raised. */
205         operator unspecified_boolean_type (); ///< Check packet availability
206                                         /**< Using any input connector in a boolean context will
207                                              check, whether an input request can be fulfilled. This
208                                              is always possible if the queue is non-empty. If the
209                                              input is active, it also returns when the connected
210                                              passive output is not throttled so new packets can be
211                                              requested. 
212
213                                              Calling the operator() member is an error if this test
214                                              returns \c false
215
216                                              \returns \c true if operator() can be called, \c false
217                                                  otherwise */
218         operator ! ();                  ///< Check packet availability
219                                         /**< Inverse of the boolean conversion operator
220                                              \returns \c false if operator() can be called, \c true
221                                                  otherwise */
222
223         OutputConnector & peer();
224
225         queue_iterator begin();         ///< Access queue begin (head)
226         queue_iterator end();           ///< Access queue past-the-end (tail)
227         Packet::ptr head();             ///< Return head element from the queue
228
229         size_type queueSize();          ///< Return number of elements in the queue
230         bool empty();                   ///< Return queueSize() == 0
231
232     protected:
233         // here to protect
234         PassiveConnector();
235         ~PassiveConnector();
236     };
237     
238     /** \brief Output connector baseclass
239         
240         An output connector sends out packets. It may be either an ActiveConnector or a
241         PassiveConnector. An output connector does \e not have an built-in queueing, it relies on
242         the queueing of the connected input.
243      */
244     class OutputConnector 
245         : public virtual Connector
246     {
247     public:
248         void operator(Packet::ptr);     ///< Send out a packet
249
250         InputConnector & peer();
251
252     protected:
253         // here to protect
254         PassiveConnector();
255         ~PassiveConnector();
256     };
257     
258     ///@{
259     ///\addtogroup connectors
260
261     /** \brief Combination of PassiveConnector and InputConnector
262
263         In addition to the native and the forwarded throttling state, the PassiveInput manages a
264         queue throttling state. This state is automatically managed by a queueing discipline. The
265         standard queueing discipline is ThresholdQueueing, which throttles the connection whenever
266         the queue length reaches the high threshold and unthrottles the connection when the queue
267         reaches the low threshold. The default queueing discipline is
268         <tt>ThresholdQueueing(1,0)</tt> which will throttle the input whenever the queue is
269         non-empty.
270      */
271     class PassiveInput 
272         : public PassiveConnector, public InputConnector
273     {
274     public:
275         ActiveOutput & peer();
276
277         template <class QueueingDiscipline>
278         void qdisc(QueueingDiscipline const & disc); ///< Change the queueing discipline
279                                         /**< The queueing discipline is a class which provides the
280                                              QueueingDiscipline interface.
281                                              
282                                              \param[in] disc New queueing discipline */
283     };
284
285     /** \brief Combination of PassiveConnector and OutputConnector
286      */
287     class PassiveOutput
288         : public PassiveConnector, public OutputConnector
289     {
290     public:
291         ActiveInput & peer();
292     };
293
294     /** \brief Combination of ActiveConnector and InputConnector
295      */
296     class ActiveInput
297         : public ActiveConnector, public InputConnector
298     {
299     public:
300         PassiveOutput & peer();
301
302         void request();                 ///< request more packets without dequeuing any packet
303     };
304
305     /** \brief Combination of ActiveConnector and OutputConnector
306      */
307     class ActiveOutput
308         : public ActiveConnector, public OutputConnector
309     {
310     public:
311         ActiveInput & peer();
312     };
313
314     ///@}
315
316 }}}
317
318 ///////////////////////////////hh.e////////////////////////////////////////
319 //#include "Conenctors.cci"
320 //#include "Conenctors.ct"
321 //#include "Conenctors.cti"
322 #endif
323
324 \f
325 // Local Variables:
326 // mode: c++
327 // fill-column: 100
328 // c-file-style: "senf"
329 // indent-tabs-mode: nil
330 // ispell-local-dictionary: "american"
331 // compile-command: "scons -u test"
332 // comment-column: 40
333 // End: