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