231b04504b91cc95848d7515cefaa7bc5741e28e
[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     /** \brief Module base-class
43
44         senf::ppi::Module is the base-class of all PPI modules. It provides the module implementation
45         with interfaces to several PPI facilities:
46         
47         \li Connector management
48         \li Flow management (routing)
49         \li Event handling
50
51         To provide internal bookkeeping, most access to the PPI infrastructure is managed through
52         this base class. This is an example module specification:
53         \code
54         class SomeModule : public senf::ppi::module::Module
55         {
56             SENF_PPI_MODULE(SomeModule);
57
58             senf::FileHandle handle;
59
60             // If needed, define events
61             senf::ppi::IOEvent event;
62
63         public:
64             // Define connectors. Any number and type of connectors may be defined. Connectors
65             // must be public since they need to be accessed to connect modules with each other.
66             senf::ppi::connector::PassiveInput input;
67             senf::ppi::connector::ActiveOutput output;
68
69             SomeModule(senf::FileHandle h) 
70               : handle ( h ), 
71                 event  ( handle, senf::ppi::IOEvent::Read )
72             {
73                 // Set up routing. If some connector is not routed you need to explicitly state this
74                 // using noroute()
75                 route( input, output );
76                 route( event, output )
77                     .autoThrottling( false );
78
79                 // Register event handlers
80                 registerEvent( &SomeModule::read, event );
81
82                 // Register passive connector handlers
83                 input.onRequest( &SomeModule::outputRequest );
84
85                 // If needed, you may register throttling event handlers
86                 output.onThrottle( &SomeModule::throttle );
87                 output.onUnthrottle( &SomeModule::unthrottle );
88             }
89
90             void read() {
91                 // Called whenever the 'handle' is readable. Read data, do processing and so
92                 // on. This example reads the data, puts it into an ethernet packet and sends the
93                 // packet out via the active output.
94                 output(senf::EthernetPacket::create(handle.read()))
95             }
96
97             void outputRequest() {
98                 // Called whenever a packet is sent into the input to. Here we just forward it to
99                 // the output if it is an EthernetPacket
100                 senf::EthernetPacket p (input().find<EthernetPacket>(senf::nothrow));
101                 if (p)
102                     output(p);
103             }
104
105             void onThrottle() {
106                 // Called whenever a throttle notification comes in. Here, we just disable the
107                 // event (which is stupid since we should just not have disabled autoThrottling on
108                 // the route but this is only an example which tries to be simple ...)
109                 event.disable();
110             }
111
112             void onUnthrottle() {
113                 // and for unthrottle notifications
114                 event.enable();
115             }
116
117         };
118         \endcode
119
120         If your module only has a single input connector, you should call this connector \c
121         input. If it has only a single output connector, you should call it \c output. This allows
122         to setup connections without stating the connector explicitly (see senf::ppi::connect()).
123      */
124     class Module
125         : boost::noncopyable
126     {
127     public:
128         virtual ~Module();
129
130     protected:
131         Module();
132
133         template <class Source, class Target>
134         Route<Source, Target> & route(Source & source, Target & target); 
135                                         ///< Define flow information
136                                         /**< Using the route() and noroute() members, the
137                                              information flow within the module is defined. Routing
138                                              may be specified either between inputs, outputs and
139                                              events. The routing information is used to perform
140                                              automatic throttling. The throttling behavior may
141                                              however be controlled manually.
142
143                                              Even if no automatic throttling is desired <em>it is
144                                              vital to define the flow information for all inputs and
145                                              outputs</em>. Without flow information important
146                                              internal state of the module cannot be
147                                              initialized. This includes, explicitly defining
148                                              terminal inputs and outputs using noroute. Event
149                                              routing however is optional.
150
151                                              The return value may be used to alter routing
152                                              parameters like throttling parameters.
153                                              
154                                              \param[in] source Data source, object which controls
155                                                  incoming data
156                                              \param[in] target Data target, object which controls
157                                                  outgoing data
158                                              \returns Route instance describing this route */
159
160         void noroute(connector::Connector & connector); ///< Define terminal connectors
161                                         /**< The noroute() member explicitly declares, that a
162                                              connector is terminal and does not directly
163                                              receive/forward data from/to some other
164                                              connector. <em>It is mandatory to define routing
165                                              information for terminal connectors</em>.
166
167                                              See the route() documentation for more on routing
168                                              
169                                              \param[in] connector Terminal connector to declare */
170
171         template <class Target, class Descriptor>
172         void registerEvent(Target target, Descriptor & descriptor);
173                                         ///< Register an external event
174                                         /**< The \a target argument may be either an arbitrary
175                                              callable object or it may be a member function pointer
176                                              pointing to a member function of the Module derived
177                                              classed. The handler may \e optionally take an Argument
178                                              of type <tt>Descriptor::Event const &</tt>. This object
179                                              allows to access detailed information on the event
180                                              delivered.
181
182                                              The \a descriptor describes the event to signal. This
183
184                                              may be a timer event or some type of I/O event on a
185                                              file descriptor or socket.
186
187                                              \param[in] target The handler to call whenever the
188                                                  event is signaled
189                                              \param[in] descriptor The type of event to register */
190
191         ClockService::clock_type time() const; ///< Time-stamp of the currently processing event
192                                         /**< If available, this returns the scheduled time of the
193                                              event. */
194
195         ClockService::clock_type now() const; ///< Current time of the currently processing event
196
197 #ifndef DOXYGEN
198         virtual void macro_SENF_PPI_MODULE_missing() = 0;
199 #endif
200
201     private:
202         virtual void init();
203
204 #ifndef DOXYGEN
205     public:
206 #endif
207         void destroy();
208         
209     private:
210         EventManager & eventManager() const;
211         ModuleManager & moduleManager() const;
212         
213         void registerConnector(connector::Connector & connector);
214         RouteBase & addRoute(std::auto_ptr<RouteBase> route);
215
216         typedef std::vector<connector::Connector *> ConnectorRegistry;
217         ConnectorRegistry connectorRegistry_;
218
219         typedef boost::ptr_vector<RouteBase> RouteInfoBase;
220         RouteInfoBase routes_;
221
222         template <class Source, class Target>
223         friend class detail::RouteHelper;
224         friend class senf::ppi::ModuleManager;
225     };
226
227 #   define SENF_PPI_MODULE(name)                                                                  \
228     public:                                                                                       \
229         ~ name() { destroy(); }                                                                   \
230         void macro_SENF_PPI_MODULE_missing() {}                                                   \
231     private:
232
233 }}}
234
235 ///////////////////////////////hh.e////////////////////////////////////////
236 #include "Module.cci"
237 #include "Module.ct"
238 //#include "Module.cti"
239 #endif
240
241 \f
242 // Local Variables:
243 // mode: c++
244 // fill-column: 100
245 // c-file-style: "senf"
246 // indent-tabs-mode: nil
247 // ispell-local-dictionary: "american"
248 // compile-command: "scons -u test"
249 // comment-column: 40
250 // End: