PPI: Delayed connect and disconnect
[senf.git] / PPI / Module.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief Module public header 
25 */
26
27 #ifndef HH_Module_
28 #define HH_Module_ 1
29
30 // Custom includes
31 #include <vector>
32 #include <boost/utility.hpp>
33 #include <boost/ptr_container/ptr_vector.hpp>
34 #include "../Scheduler/ClockService.hh"
35 #include "predecl.hh"
36 #include "ModuleManager.hh"
37
38 //#include "Module.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
40
41 namespace senf {
42 namespace ppi {
43 namespace module {
44
45     /** \namespace senf::ppi::module
46         \brief PPI Modules
47        
48         The modules build the PPI core. The PPI provides a set of general purpose infrastructure
49         modules. For concrete applications, additional application specific processing modules need
50         to be implemented.
51
52         \section module_impl Implementing Modules
53         
54         All modules derive from senf::ppi::module::Module. See this class for a documentation on how
55         to write new modules.
56
57         \section infrastructure_modules General Purpose Modules
58
59         The PPI provided general purpose modules can be grouped into several categories
60
61         \li \ref io_modules receive external data or forward packets out of the PPI
62         \li \ref routing_modules forward packets within the network
63         \li \ref adapter_modules are used to connect incompatible connectors to each other
64
65         \todo Implement Spliters: PassiveSplitter, PrioritySplitter, CloneSplitter
66      */
67
68     /** \defgroup io_modules Source/Sink Modules
69
70         Source and Sink modules generate or absorb packets in some way: Reading data from a file
71         descriptor, discarding packets etc.
72      */
73
74     /** \defgroup routing_modules Routing Modules
75
76         Routing modules perform packet forwarding within the network. They do not process the packet
77         data, they just route it.
78      */
79
80     /** \defgroup adapter_modules Adapter Modules
81
82         Adapter modules adapt incompatible connectors to each other. They allow connection a pair of
83         active or passive connectors.
84      */
85
86     /** \brief Module base-class
87
88         senf::ppi::Module is the base-class of all PPI modules. It provides the module implementation
89         with interfaces to several PPI facilities:
90         
91         \li Connector management
92         \li Flow management (routing)
93         \li Event handling
94
95         To provide internal bookkeeping, most access to the PPI infrastructure is managed through
96         this base class. This is an example module specification:
97         \code
98         class SomeModule : public senf::ppi::module::Module
99         {
100             SENF_PPI_MODULE(SomeModule);
101
102             senf::FileHandle handle;
103
104             // If needed, define events
105             senf::ppi::IOEvent event;
106
107         public:
108             // Define connectors. Any number and type of connectors may be defined. Connectors
109             // must be public since they need to be accessed to connect modules with each other.
110             senf::ppi::connector::PassiveInput<> input;
111             senf::ppi::connector::ActiveOutput<> output;
112
113             SomeModule(senf::FileHandle h) 
114               : handle ( h ), 
115                 event  ( handle, senf::ppi::IOEvent::Read )
116             {
117                 // Set up routing. If some connector is not routed you need to explicitly state this
118                 // using noroute()
119                 route( input, output );
120                 route( event, output )
121                     .autoThrottling( false );
122
123                 // Register event handlers
124                 registerEvent( event, &SomeModule::read );
125
126                 // Register passive connector handlers
127                 input.onRequest( &SomeModule::outputRequest );
128
129                 // If needed, you may register throttling event handlers
130                 output.onThrottle( &SomeModule::throttle );
131                 output.onUnthrottle( &SomeModule::unthrottle );
132             }
133
134             void read() {
135                 // Called whenever the 'handle' is readable. Read data, do processing and so
136                 // on. This example reads the data, puts it into an ethernet packet and sends the
137                 // packet out via the active output.
138                 output(senf::EthernetPacket::create(handle.read()))
139             }
140
141             void outputRequest() {
142                 // Called whenever a packet is sent into the input to. Here we just forward it to
143                 // the output if it is an EthernetPacket
144                 senf::EthernetPacket p (input().find<EthernetPacket>(senf::nothrow));
145                 if (p)
146                     output(p);
147             }
148
149             void onThrottle() {
150                 // Called whenever a throttle notification comes in. Here, we just disable the
151                 // event (which is stupid since we should just not have disabled autoThrottling on
152                 // the route but this is only an example which tries to be simple ...)
153                 event.disable();
154             }
155
156             void onUnthrottle() {
157                 // and for unthrottle notifications
158                 event.enable();
159             }
160
161         };
162         \endcode
163
164         If your module only has a single input connector, you should call this connector \c
165         input. If it has only a single output connector, you should call it \c output. This allows
166         to setup connections without stating the connector explicitly (see senf::ppi::connect()).
167
168         \see \ref ppi_modules
169      */
170     class Module
171         : ModuleManager::Initializable, boost::noncopyable
172     {
173     public:
174         virtual ~Module();
175
176     protected:
177         Module();
178
179 #ifndef DOXYGEN
180         template <class Source, class Target>
181         Route<Source, Target> & route(Source & source, Target & target); 
182 #else
183         Route<connector::InputConnector, connector::OutputConnector> &
184         route(connector::InputConnector & input, connector::OutputConnector & output);
185                                         ///< Define flow information
186                                         /**< Using the route() and noroute() members, the
187                                              information flow within the module is defined. Routing
188                                              may be defined between inputs, outputs and events. The
189                                              routing information is used to perform automatic
190                                              throttling. The throttling behavior may however be
191                                              controlled manually.
192
193                                              Even if no automatic throttling is desired <em>it is
194                                              essential to define the flow information for all inputs
195                                              and outputs</em>. Without flow information important
196                                              internal state of the module cannot be
197                                              initialized. This includes, explicitly defining
198                                              terminal inputs and outputs using noroute. Event
199                                              routing is optional however.
200
201                                              The return value may be used to alter routing
202                                              parameters like throttling parameters.
203
204                                              \param[in] input Data source, object which controls
205                                                  incoming data (connector or event)
206                                              \param[in] output Data target, object which controls
207                                                  outgoing data (connector or event)
208                                              \returns Route instance describing this route 
209                                              \see \ref ppi_throttling
210                                              \note The real implementation is not provided by three
211                                                  overloads but by a single template member */
212
213         Route<connector::InputConnector, EventDescriptor> &
214         route(connector::InputConnector & input, EventDescriptor & output);
215                                         ///< Define flow information
216                                         /**< Route from a connector to an event.  Routing from a
217                                              connector to an event defines the event as the
218                                              conceptual 'receiver' of the data. This means, the
219                                              event is controlling the processing of received data
220                                              packets (Example: Routing from an input to an IOEvent
221                                              defines, that input data will be processed whenever the
222                                              event is signaled.).
223
224                                              This event routing allows to automatically
225                                              enable/disable the event on throttling notifications. 
226
227                                              \see \ref route() */
228
229         Route<EventDescriptor, connector::OutputConnector> &
230         route(EventDescriptor & input, connector::OutputConnector & output);
231                                         ///< Define flow information
232                                         /**< Route from an event to a connector. Routing from an
233                                              event to a connector defines the event as the
234                                              conceptual 'source' of the data. This means, the event
235                                              controls how packets are sent (Example: Routing from an
236                                              IOEvent to an output defines, that output data will be
237                                              generated whenever the event is signaled).
238
239                                              This event routing allows to automatically
240                                              enable/disable the event on throttling notifications. 
241
242                                              \see \ref route() */
243 #endif
244
245         void noroute(connector::Connector & connector); ///< Define terminal connectors
246                                         /**< The noroute() member explicitly declares, that a
247                                              connector is terminal and does not directly
248                                              receive/forward data from/to some other
249                                              connector. <em>It is mandatory to define routing
250                                              information for terminal connectors</em>.
251
252                                              See the route() documentation for more on routing
253                                              
254                                              \param[in] connector Terminal connector to declare */
255
256 #ifndef DOXYGEN
257         template <class Descriptor, class Target>
258         void registerEvent(Descriptor & descriptor, Target target);
259 #else
260         template <class Target>
261         void registerEvent(EventDescriptor & descriptor, Target target);
262                                         ///< Register an external event
263                                         /**< The \a target argument may be either an arbitrary
264                                              callable object or it may be a member function pointer
265                                              pointing to a member function of the Module derived
266                                              classed. The handler may \e optionally take an Argument
267                                              of type <tt>Descriptor::Event const &</tt>. This object
268                                              allows to access detailed information on the event
269                                              delivered.
270
271                                              The \a descriptor describes the event to signal like a
272                                              timer event or some type of I/O event on a file
273                                              descriptor or socket.
274
275                                              \param[in] target The handler to call whenever the
276                                                  event is signaled
277                                              \param[in] descriptor The type of event to register 
278                                              \note The real implementation has the second arguments
279                                                  type as an additional template parameter. */
280 #endif
281
282         ClockService::clock_type time() const; ///< Time-stamp of the currently processing event
283                                         /**< If available, this returns the scheduled time of the
284                                              event. */
285
286         ClockService::clock_type now() const; ///< Current time of the currently processing event
287
288 #ifndef DOXYGEN
289         virtual void macro_SENF_PPI_MODULE_missing() = 0;
290
291     private:
292 #endif
293         virtual void v_init();
294
295 #ifndef DOXYGEN
296     public:
297 #endif
298         void destroy();
299         
300     private:
301         EventManager & eventManager() const;
302         ModuleManager & moduleManager() const;
303         
304         void registerConnector(connector::Connector & connector);
305         RouteBase & addRoute(std::auto_ptr<RouteBase> route);
306
307         typedef std::vector<connector::Connector *> ConnectorRegistry;
308         ConnectorRegistry connectorRegistry_;
309
310         typedef boost::ptr_vector<RouteBase> RouteInfoBase;
311         RouteInfoBase routes_;
312
313         template <class Source, class Target>
314         friend class detail::RouteHelper;
315         friend class senf::ppi::ModuleManager;
316     };
317
318     /** \brief Define PPI Module
319
320         Every module must begin by using this macro. 
321
322         \see senf::ppi::module::Module
323      */
324 #   define SENF_PPI_MODULE(name)                                                                  \
325     public:                                                                                       \
326         ~ name() { destroy(); }                                                                   \
327         void macro_SENF_PPI_MODULE_missing() {}                                                   \
328     private:
329
330 }}}
331
332 ///////////////////////////////hh.e////////////////////////////////////////
333 #include "Module.cci"
334 #include "Module.ct"
335 //#include "Module.cti"
336 #endif
337
338 \f
339 // Local Variables:
340 // mode: c++
341 // fill-column: 100
342 // c-file-style: "senf"
343 // indent-tabs-mode: nil
344 // ispell-local-dictionary: "american"
345 // compile-command: "scons -u test"
346 // comment-column: 40
347 // End: