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