#define HH_Module_ 1
// Custom includes
+#include <vector>
#include <boost/utility.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+#include "../Scheduler/ClockService.hh"
+#include "predecl.hh"
//#include "Module.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace ppi {
namespace module {
- /** \brief Module baseclass
+ /** \namespace senf::ppi::module
+ \brief PPI Modules
+
+ The modules build the PPI core. The PPI provides a set of general purpose infrastructure
+ modules. For concrete applications, additional application specific processing modules need
+ to be implemented.
- senf::ppi::Module is the baseclass of all PPI modules. It provides the module implementation
+ \section module_impl Implementing Modules
+
+ All modules derive from senf::ppi::module::Module. See this class for a documentation on how
+ to write new modules.
+
+ \section infrastructure_modules General Purpose Modules
+
+ The PPI provided general purpose modules can be grouped into several categories
+
+ \li \ref io_modules receive external data or forward packets out of the PPI
+ \li \ref sourcesink_modules generate or absorb packets internally
+ \li \ref routing_modules forward packets within the network
+ \li \ref adapter_modules are used to connect incompatible connectors to each other
+
+ \todo Implement Spliters: PassiveSplitter, PrioritySplitter, CloneSplitter
+ */
+
+ /** \defgroup io_modules Input/Output Modules
+
+ Input/Output Modules receive data from external sources or forward data from the PPI to
+ outside targets.
+ */
+
+ /** \defgroup sourcesink_modules Source/Sink Modules
+
+ Source and Sink modules generate or absorb packets internally. In contrast to \ref
+ io_modules, they do not communicate outside the PPI.
+ */
+
+ /** \defgroup routing_modules Routing Modules
+
+ Routing modules perform packet forwarding within the network. They do not process the packet
+ data, they just route it.
+ */
+
+ /** \defgroup adapter_modules Adapter Modules
+
+ Adapter modules adapt incompatible connectors to each other. They allow connection a pair of
+ active or passive connectors.
+ */
+
+ /** \brief Module base-class
+
+ senf::ppi::Module is the base-class of all PPI modules. It provides the module implementation
with interfaces to several PPI facilities:
\li Connector management
\li Event handling
To provide internal bookkeeping, most access to the PPI infrastructure is managed through
- this base class.
+ this base class. This is an example module specification:
+ \code
+ class SomeModule : public senf::ppi::module::Module
+ {
+ SENF_PPI_MODULE(SomeModule);
+
+ senf::FileHandle handle;
+
+ // If needed, define events
+ senf::ppi::IOEvent event;
+
+ public:
+ // Define connectors. Any number and type of connectors may be defined. Connectors
+ // must be public since they need to be accessed to connect modules with each other.
+ senf::ppi::connector::PassiveInput input;
+ senf::ppi::connector::ActiveOutput output;
+
+ SomeModule(senf::FileHandle h)
+ : handle ( h ),
+ event ( handle, senf::ppi::IOEvent::Read )
+ {
+ // Set up routing. If some connector is not routed you need to explicitly state this
+ // using noroute()
+ route( input, output );
+ route( event, output )
+ .autoThrottling( false );
- Instances of this class may be allocated either statically or dynamically. Dynamic instances
- are automatically managed using the dynamicModule adaptor.
+ // Register event handlers
+ registerEvent( &SomeModule::read, event );
+
+ // Register passive connector handlers
+ input.onRequest( &SomeModule::outputRequest );
+
+ // If needed, you may register throttling event handlers
+ output.onThrottle( &SomeModule::throttle );
+ output.onUnthrottle( &SomeModule::unthrottle );
+ }
+
+ void read() {
+ // Called whenever the 'handle' is readable. Read data, do processing and so
+ // on. This example reads the data, puts it into an ethernet packet and sends the
+ // packet out via the active output.
+ output(senf::EthernetPacket::create(handle.read()))
+ }
+
+ void outputRequest() {
+ // Called whenever a packet is sent into the input to. Here we just forward it to
+ // the output if it is an EthernetPacket
+ senf::EthernetPacket p (input().find<EthernetPacket>(senf::nothrow));
+ if (p)
+ output(p);
+ }
+
+ void onThrottle() {
+ // Called whenever a throttle notification comes in. Here, we just disable the
+ // event (which is stupid since we should just not have disabled autoThrottling on
+ // the route but this is only an example which tries to be simple ...)
+ event.disable();
+ }
+
+ void onUnthrottle() {
+ // and for unthrottle notifications
+ event.enable();
+ }
+
+ };
+ \endcode
+
+ If your module only has a single input connector, you should call this connector \c
+ input. If it has only a single output connector, you should call it \c output. This allows
+ to setup connections without stating the connector explicitly (see senf::ppi::connect()).
*/
class Module
: boost::noncopyable
{
+ public:
+ virtual ~Module();
+
protected:
Module();
- ~Module();
template <class Source, class Target>
- Route<Source, Target> & route(Source const & source, Target const & target);
+ Route<Source, Target> & route(Source & source, Target & target);
///< Define flow information
/**< Using the route() and noroute() members, the
information flow within the module is defined. Routing
outgoing data
\returns Route instance describing this route */
- template <class Connector>
- void noroute(Connector const & connector); ///< Define terminal connectors
+ void noroute(connector::Connector & connector); ///< Define terminal connectors
/**< The noroute() member explicitly declares, that a
connector is terminal and does not directly
receive/forward data from/to some other
\param[in] connector Terminal connector to declare */
template <class Target, class Descriptor>
- void registerEvent(Target target, Descriptor const & descriptor);
+ void registerEvent(Target target, Descriptor & descriptor);
///< Register an external event
/**< The \a target argument may be either an arbitrary
callable object or it may be a member function pointer
pointing to a member function of the Module derived
classed. The handler may \e optionally take an Argument
- of type <tt>typename Descriptor::Event const
- &</tt>. This object allows to access detailed
- information on the event delivered.
+ of type <tt>Descriptor::Event const &</tt>. This object
+ allows to access detailed information on the event
+ delivered.
The \a descriptor describes the event to signal. This
+
may be a timer event or some type of I/O event on a
file descriptor or socket.
event is signaled
\param[in] descriptor The type of event to register */
- boost::posix_time::ptime eventTime(); ///< Return timestamp of the currently processing
- ///< event
+ ClockService::clock_type time() const; ///< Time-stamp of the currently processing event
+ /**< If available, this returns the scheduled time of the
+ event. */
+
+ ClockService::clock_type now() const; ///< Current time of the currently processing event
+
+#ifndef DOXYGEN
+ virtual void macro_SENF_PPI_MODULE_missing() = 0;
+#endif
+
+#ifndef DOXYGEN
+ private:
+#endif
+ virtual void init(); ///< Called just before the network is run
+
+#ifndef DOXYGEN
+ public:
+#endif
+ void destroy();
+
+ private:
+ EventManager & eventManager() const;
+ ModuleManager & moduleManager() const;
+
+ void registerConnector(connector::Connector & connector);
+ RouteBase & addRoute(std::auto_ptr<RouteBase> route);
+
+ typedef std::vector<connector::Connector *> ConnectorRegistry;
+ ConnectorRegistry connectorRegistry_;
+
+ typedef boost::ptr_vector<RouteBase> RouteInfoBase;
+ RouteInfoBase routes_;
+
+ template <class Source, class Target>
+ friend class detail::RouteHelper;
+ friend class senf::ppi::ModuleManager;
};
- /** \brief Connect compatible connectors
+ /** \brief Define PPI Module
+
+ Every module must begin by using this macro.
- connect() will connect two compatible connectors: One connector must be active, the other
- passive.
+ \see senf::ppi::module::Module
*/
- template <class Source, class Target>
- void connect(Source const & source, Target const & target);
+# define SENF_PPI_MODULE(name) \
+ public: \
+ ~ name() { destroy(); } \
+ void macro_SENF_PPI_MODULE_missing() {} \
+ private:
}}}
///////////////////////////////hh.e////////////////////////////////////////
-//#include "Module.cci"
-//#include "Module.ct"
+#include "Module.cci"
+#include "Module.ct"
//#include "Module.cti"
#endif
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
+// comment-column: 40
// End: