4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
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
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.
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.
19 // The Original Code is Fraunhofer FOKUS code.
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.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief Module public header
32 #ifndef HH_SENF_PPI_Module_
33 #define HH_SENF_PPI_Module_ 1
37 #include <boost/utility.hpp>
38 #include <boost/ptr_container/ptr_vector.hpp>
39 #include <senf/Scheduler/ClockService.hh>
41 #include "ModuleManager.hh"
43 //#include "Module.mpp"
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
49 namespace detail { class EventBindingBase; }
53 /** \namespace senf::ppi::module
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
60 \section module_impl Implementing Modules
62 All modules derive from senf::ppi::module::Module. See this class for a documentation on how
65 \section infrastructure_modules General Purpose Modules
67 The PPI provided general purpose modules can be grouped into several categories
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
74 /** \defgroup io_modules Source/Sink Modules
76 Source and Sink modules generate or absorb packets in some way: Reading data from a file
77 descriptor, discarding packets etc.
80 /** \defgroup routing_modules Routing Modules
82 Routing modules perform packet forwarding within the network. They do not process the packet
83 data, they just route it.
86 /** \defgroup adapter_modules Adapter Modules
88 Adapter modules adapt incompatible connectors to each other. They allow connection a pair of
89 active or passive connectors.
92 /** \brief Module base-class
94 senf::ppi::Module is the base-class of all PPI modules. It provides the module implementation
95 with interfaces to several PPI facilities:
97 \li Connector management
98 \li Flow management (routing)
101 To provide internal bookkeeping, most access to the PPI infrastructure is managed through
102 this base class. This is an example module specification:
104 class SomeModule : public senf::ppi::module::Module
106 SENF_PPI_MODULE(SomeModule);
108 senf::FileHandle handle;
110 // If needed, define events
111 senf::ppi::IOEvent event;
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;
119 SomeModule(senf::FileHandle h)
121 event ( handle, senf::ppi::IOEvent::Read )
123 // Set up routing. If some connector is not routed you need to explicitly state this
125 route( input, output );
126 route( event, output )
127 .autoThrottling( false );
129 // Register event handlers
130 registerEvent( event, &SomeModule::read );
132 // Register passive connector handlers
133 input.onRequest( &SomeModule::outputRequest );
135 // If needed, you may register throttling event handlers
136 output.onThrottle( &SomeModule::throttle );
137 output.onUnthrottle( &SomeModule::unthrottle );
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()))
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));
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 ...)
162 void onUnthrottle() {
163 // and for unthrottle notifications
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.
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()).
181 \see \ref ppi_modules
184 : ModuleManager::Initializable, boost::noncopyable
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
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.
211 The return value may be used to alter routing
212 parameters like throttling parameters.
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 */
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
232 This event routing allows to automatically
233 enable/disable the event on throttling notifications.
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).
247 This event routing allows to automatically
248 enable/disable the event on throttling notifications.
252 # define route_decl(Source, Target) \
253 Route<Source, Target> & \
254 route(Source & source, Target & target);
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);
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>.
275 See the route() documentation for more on routing
277 \param[in] connector Terminal connector to declare */
280 template <class Descriptor, class Target>
281 void registerEvent(Descriptor & descriptor, Target target);
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
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.
298 \param[in] target The handler to call whenever the
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. */
305 ClockService::clock_type time() const; ///< Time-stamp of the currently processing event
306 /**< If available, this returns the scheduled time of the
309 ClockService::clock_type now() const; ///< Current time of the currently processing event
312 virtual void macro_SENF_PPI_MODULE_missing() = 0;
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.
321 You may overload this member. Your overload should
322 always call the base-class implementation. */
330 EventManager & eventManager() const;
331 ModuleManager & moduleManager() const;
333 void registerConnector(connector::Connector & connector);
334 void unregisterConnector(connector::Connector & connector);
335 void unregisterEvent(EventDescriptor & event);
337 RouteBase & addRoute(std::auto_ptr<RouteBase> route);
339 typedef std::vector<connector::Connector *> ConnectorRegistry;
340 ConnectorRegistry connectorRegistry_;
342 typedef boost::ptr_vector<RouteBase> RouteInfoBase;
343 RouteInfoBase routes_;
345 template <class Source, class Target>
346 friend struct detail::RouteHelper;
347 friend class senf::ppi::ModuleManager;
348 friend class connector::Connector;
349 friend class senf::ppi::detail::EventBindingBase;
352 /** \brief Define PPI Module
354 Every module must begin by using this macro.
356 \see senf::ppi::module::Module
358 # define SENF_PPI_MODULE(name) \
360 ~ name() { destroy(); } \
361 void macro_SENF_PPI_MODULE_missing() {} \
366 //-/////////////////////////////////////////////////////////////////////////////////////////////////
367 #include "Module.cci"
369 //#include "Module.cti"
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