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