g++/final: don't add extra code to check for buffer overflows (-fno-stack-protector)
[senf.git] / senf / PPI / Module.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Module public header
30 */
31
32 #ifndef HH_SENF_PPI_Module_
33 #define HH_SENF_PPI_Module_ 1
34
35 // Custom includes
36 #include <vector>
37 #include <boost/utility.hpp>
38 #include <boost/ptr_container/ptr_vector.hpp>
39 #include <senf/Scheduler/ClockService.hh>
40 #include "predecl.hh"
41 #include "ModuleManager.hh"
42
43 //#include "Module.mpp"
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45
46 namespace senf {
47 namespace ppi {
48
49     namespace detail { class EventBindingBase; }
50
51 namespace module {
52
53     /** \namespace senf::ppi::module
54         \brief PPI Modules
55
56         The modules build the PPI core. The PPI provides a set of general purpose infrastructure
57         modules. For concrete applications, additional application specific processing modules need
58         to be implemented.
59
60         \section module_impl Implementing Modules
61
62         All modules derive from senf::ppi::module::Module. See this class for a documentation on how
63         to write new modules.
64
65         \section infrastructure_modules General Purpose Modules
66
67         The PPI provided general purpose modules can be grouped into several categories
68
69         \li \ref io_modules receive external data or forward packets out of the PPI
70         \li \ref routing_modules forward packets within the network
71         \li \ref adapter_modules are used to connect incompatible connectors to each other
72      */
73
74     /** \defgroup io_modules Source/Sink Modules
75
76         Source and Sink modules generate or absorb packets in some way: Reading data from a file
77         descriptor, discarding packets etc.
78      */
79
80     /** \defgroup routing_modules Routing Modules
81
82         Routing modules perform packet forwarding within the network. They do not process the packet
83         data, they just route it.
84      */
85
86     /** \defgroup adapter_modules Adapter Modules
87
88         Adapter modules adapt incompatible connectors to each other. They allow connection a pair of
89         active or passive connectors.
90      */
91
92     /** \brief Module base-class
93
94         senf::ppi::Module is the base-class of all PPI modules. It provides the module implementation
95         with interfaces to several PPI facilities:
96
97         \li Connector management
98         \li Flow management (routing)
99         \li Event handling
100
101         To provide internal bookkeeping, most access to the PPI infrastructure is managed through
102         this base class. This is an example module specification:
103         \code
104         class SomeModule : public senf::ppi::module::Module
105         {
106             SENF_PPI_MODULE(SomeModule);
107
108             senf::FileHandle handle;
109
110             // If needed, define events
111             senf::ppi::IOEvent event;
112
113         public:
114             // Define connectors. Any number and type of connectors may be defined. Connectors
115             // must be public since they need to be accessed to connect modules with each other.
116             senf::ppi::connector::PassiveInput<> input;
117             senf::ppi::connector::ActiveOutput<> output;
118
119             SomeModule(senf::FileHandle h)
120               : handle ( h ),
121                 event  ( handle, senf::ppi::IOEvent::Read )
122             {
123                 // Set up routing. If some connector is not routed you need to explicitly state this
124                 // using noroute()
125                 route( input, output );
126                 route( event, output )
127                     .autoThrottling( false );
128
129                 // Register event handlers
130                 registerEvent( event, &SomeModule::read );
131
132                 // Register passive connector handlers
133                 input.onRequest( &SomeModule::outputRequest );
134
135                 // If needed, you may register throttling event handlers
136                 output.onThrottle( &SomeModule::throttle );
137                 output.onUnthrottle( &SomeModule::unthrottle );
138             }
139
140             void read() {
141                 // Called whenever the 'handle' is readable. Read data, do processing and so
142                 // on. This example reads the data, puts it into an ethernet packet and sends the
143                 // packet out via the active output.
144                 output(senf::EthernetPacket::create(handle.read()))
145             }
146
147             void outputRequest() {
148                 // Called whenever a packet is sent into the input to. Here we just forward it to
149                 // the output if it is an EthernetPacket
150                 senf::EthernetPacket p (input().find<EthernetPacket>(senf::nothrow));
151                 if (p)
152                     output(p);
153             }
154
155             void onThrottle() {
156                 // Called whenever a throttle notification comes in. Here, we just disable the
157                 // event (which is stupid since we should just not have disabled autoThrottling on
158                 // the route but this is only an example which tries to be simple ...)
159                 event.disable();
160             }
161
162             void onUnthrottle() {
163                 // and for unthrottle notifications
164                 event.enable();
165             }
166
167             void v_init() {
168                 // Optional. Called after before running the module but after connections have been
169                 // set up. This is either directly before senf::ppi::run() or senf::ppi::init() is
170                 // called or, for modules created while the PPI is already running, after returning
171                 // from all event handlers but before going back to the event loop.
172             }
173
174         };
175         \endcode
176
177         If your module only has a single input connector, you should call this connector \c
178         input. If it has only a single output connector, you should call it \c output. This allows
179         to setup connections without stating the connector explicitly (see senf::ppi::connect()).
180
181         \see \ref ppi_modules
182      */
183     class Module
184         : ModuleManager::Initializable, boost::noncopyable
185     {
186     public:
187         virtual ~Module();
188
189     protected:
190         Module();
191
192 #ifdef DOXYGEN
193         Route<connector::InputConnector, connector::OutputConnector> &
194         route(connector::InputConnector & input, connector::OutputConnector & output);
195                                         ///< Define flow information
196                                         /**< Using the route() and noroute() members, the
197                                              information flow within the module is defined. Routing
198                                              may be defined between inputs, outputs and events. The
199                                              routing information is used to perform automatic
200                                              throttling. The throttling behavior may however be
201                                              controlled manually.
202
203                                              Even if no automatic throttling is desired <em>it is
204                                              essential to define the flow information for all inputs
205                                              and outputs</em>. Without flow information important
206                                              internal state of the module cannot be
207                                              initialized. This includes, explicitly defining
208                                              terminal inputs and outputs using noroute. Event
209                                              routing is optional however.
210
211                                              The return value may be used to alter routing
212                                              parameters like throttling parameters.
213
214                                              \param[in] input Data source, object which controls
215                                                  incoming data (connector or event)
216                                              \param[in] output Data target, object which controls
217                                                  outgoing data (connector or event)
218                                              \returns Route instance describing this route
219                                              \see \ref ppi_throttling */
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 #else
252 #       define route_decl(Source, Target)               \
253             Route<Source, Target> &                     \
254             route(Source & source, Target & target);
255
256         route_decl( connector::GenericPassiveInput, connector::GenericActiveOutput);
257         route_decl( connector::GenericPassiveInput, connector::GenericPassiveOutput);
258         route_decl( connector::GenericActiveInput,  connector::GenericPassiveOutput);
259         route_decl( connector::GenericActiveInput,  connector::GenericActiveOutput);
260         route_decl( connector::GenericPassiveInput, EventDescriptor);
261         route_decl( connector::GenericActiveInput,  EventDescriptor);
262         route_decl( EventDescriptor, connector::GenericPassiveOutput);
263         route_decl( EventDescriptor, connector::GenericActiveOutput);
264
265 #undef Route_decl
266 #endif
267
268         void noroute(connector::Connector & connector); ///< Define terminal connectors
269                                         /**< The noroute() member explicitly declares, that a
270                                              connector is terminal and does not directly
271                                              receive/forward data from/to some other
272                                              connector. <em>It is mandatory to define routing
273                                              information for terminal connectors</em>.
274
275                                              See the route() documentation for more on routing
276
277                                              \param[in] connector Terminal connector to declare */
278
279 #ifndef DOXYGEN
280         template <class Descriptor, class Target>
281         void registerEvent(Descriptor & descriptor, Target target);
282 #else
283         template <class Target>
284         void registerEvent(EventDescriptor & descriptor, Target target);
285                                         ///< Register an external event
286                                         /**< The \a target argument may be either an arbitrary
287                                              callable object or it may be a member function pointer
288                                              pointing to a member function of the Module derived
289                                              classed. The handler may \e optionally take an Argument
290                                              of type <tt>Descriptor::Event const &</tt>. This object
291                                              allows to access detailed information on the event
292                                              delivered.
293
294                                              The \a descriptor describes the event to signal like a
295                                              timer event or some type of I/O event on a file
296                                              descriptor or socket.
297
298                                              \param[in] target The handler to call whenever the
299                                                  event is signaled
300                                              \param[in] descriptor The type of event to register
301                                              \note The real implementation has the second arguments
302                                                  type as an additional template parameter. */
303 #endif
304
305         ClockService::clock_type time() const; ///< Time-stamp of the currently processing event
306                                         /**< If available, this returns the scheduled time of the
307                                              event. */
308
309         ClockService::clock_type now() const; ///< Current time of the currently processing event
310
311 #ifndef DOXYGEN
312         virtual void macro_SENF_PPI_MODULE_missing() = 0;
313
314     private:
315 #endif
316         virtual void v_init();          ///< Called after module setup
317                                         /**< This member is called directly before the PPI (resumes)
318                                              execution. It is called after connections have been
319                                              setup before entering the PPI main loop.
320
321                                              You may overload this member. Your overload should
322                                              always call the base-class implementation. */
323
324 #ifndef DOXYGEN
325     public:
326 #endif
327         void destroy();
328
329     private:
330         EventManager & eventManager() const;
331         ModuleManager & moduleManager() const;
332
333         void registerConnector(connector::Connector & connector);
334         void unregisterConnector(connector::Connector & connector);
335         void unregisterEvent(EventDescriptor & event);
336
337         RouteBase & addRoute(std::auto_ptr<RouteBase> route);
338
339         typedef std::vector<connector::Connector *> ConnectorRegistry;
340         ConnectorRegistry connectorRegistry_;
341
342         typedef boost::ptr_vector<RouteBase> RouteInfoBase;
343         RouteInfoBase routes_;
344
345         template <class Source, class Target>
346         friend class detail::RouteHelper;
347         friend class senf::ppi::ModuleManager;
348         friend class connector::Connector;
349         friend class senf::ppi::detail::EventBindingBase;
350     };
351
352     /** \brief Define PPI Module
353
354         Every module must begin by using this macro.
355
356         \see senf::ppi::module::Module
357      */
358 #   define SENF_PPI_MODULE(name)                                                                  \
359     public:                                                                                       \
360         ~ name() { destroy(); }                                                                   \
361         void macro_SENF_PPI_MODULE_missing() {}                                                   \
362     private:
363
364 }}}
365
366 //-/////////////////////////////////////////////////////////////////////////////////////////////////
367 #include "Module.cci"
368 #include "Module.ct"
369 //#include "Module.cti"
370 #endif
371
372 \f
373 // Local Variables:
374 // mode: c++
375 // fill-column: 100
376 // c-file-style: "senf"
377 // indent-tabs-mode: nil
378 // ispell-local-dictionary: "american"
379 // compile-command: "scons -u test"
380 // comment-column: 40
381 // End: