Socket: Ignore ECONNREFUSED on write to datagram socket
[senf.git] / PPI / Module.hh
index 24fdf0c..aac6bfa 100644 (file)
@@ -39,9 +39,55 @@ namespace senf {
 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.
+
+        \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
+     */
+
+    /** \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 baseclass of all PPI modules. It provides the module implementation
+        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
@@ -49,10 +95,77 @@ namespace module {
         \li Event handling
 
         To provide internal bookkeeping, most access to the PPI infrastructure is managed through
-        this base class. 
-
-        Instances of this class may be allocated either statically or dynamically. Dynamic instances
-        are automatically managed using the dynamicModule adaptor.
+        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 );
+
+                // 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
@@ -108,9 +221,9 @@ namespace module {
                                              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
 
@@ -121,20 +234,27 @@ namespace module {
                                                  event is signaled
                                              \param[in] descriptor The type of event to register */
 
-        ClockService::clock_type time() const; ///< Return timestamp of the currently processing
-                                        ///< event
-
-        ClockService::clock_type now() const;
+        ClockService::clock_type time() const; ///< Time-stamp of the currently processing event
+                                        /**< If available, this returns the scheduled time of the
+                                             event. */
 
-        void destroy();
+        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:
-        virtual void init();
+#endif
+        virtual void init();            ///< Called just before the network is run
 
+#ifndef DOXYGEN
+    public:
+#endif
+        void destroy();
+        
+    private:
         EventManager & eventManager() const;
         ModuleManager & moduleManager() const;
         
@@ -152,6 +272,12 @@ namespace module {
         friend class senf::ppi::ModuleManager;
     };
 
+    /** \brief Define PPI Module
+
+        Every module must begin by using this macro. 
+
+        \see senf::ppi::module::Module
+     */
 #   define SENF_PPI_MODULE(name)                                                                  \
     public:                                                                                       \
         ~ name() { destroy(); }                                                                   \