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