PPI: Implement LogWriter
g0dil [Thu, 23 Aug 2007 22:40:59 +0000 (22:40 +0000)]
PPI: Add documentation
Utils: Make Logger macros define empty stub types

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@407 270642c3-0616-0410-b53a-bc976706d245

24 files changed:
PPI/ActiveFeeder.hh
PPI/Connectors.hh
PPI/DebugEvent.hh
PPI/DebugModules.cti [new file with mode: 0644]
PPI/DebugModules.hh
PPI/DebugModules.test.cc
PPI/EventManager.hh
PPI/Events.hh
PPI/Events.ih
PPI/IOEvent.hh
PPI/IdleEvent.hh
PPI/IntervalTimer.hh
PPI/Mainpage.dox
PPI/Module.hh
PPI/Module.ih
PPI/ModuleManager.cc
PPI/ModuleManager.hh
PPI/Route.hh
PPI/Route.ih
PPI/SocketReader.hh
PPI/detail/EventBinding.hh
PPI/predecl.hh
Utils/Logger.hh
senf.dict

index a545050..d981c46 100644 (file)
@@ -38,6 +38,15 @@ namespace senf {
 namespace ppi {
 namespace module {
 
+    /** \brief Adapter to connect passive connectors
+
+        ActiveFeeder is an adapter module which allows to connect to passive connectors. As long as
+        none of the connectors is throttled, the ActiveFeeder will forward packets from it's input
+        to it's output.
+
+        \note For this Module to work correctly, it is very important for the connectors to be
+            correctly throttled. Otherwise the system might well hang in an endless loop.
+     */
     class ActiveFeeder
         : public Module
     {
index 3824628..e37ad1f 100644 (file)
@@ -57,7 +57,11 @@ namespace senf {
 namespace ppi {
 namespace connector {
 
-    /** \brief Connector baseclass
+    /** \namespace senf::ppi::connector
+        \brief Connector classes 
+     */
+
+    /** \brief Connector base-class
 
         This connector provides access to the generic connector facilities. This includes the
         connection management (access to the connected peer) and the containment management (access
@@ -85,7 +89,7 @@ namespace connector {
         friend class module::Module;
     };
 
-    /** \brief Passive connector baseclass
+    /** \brief Passive connector base-class
 
         A passive connector is a connector which is activated externally whenever an I/O request
         occurs. Passive connectors are the origin of throttling notifications. Depending on the type
@@ -134,8 +138,8 @@ namespace connector {
 
     private:
         // Called by the routing to change the remote throttling state
-        void notifyThrottle();          ///< Forward a throttling notification to this connector
-        void notifyUnthrottle();        ///< Forward an unthrottling notification to this connector
+        void notifyThrottle();          ///< Forward a throttle notification to this connector
+        void notifyUnthrottle();        ///< Forward an unthrottle notification to this connector
 
         // Internal members to emit throttling notifications
         void emitThrottle();
@@ -159,7 +163,7 @@ namespace connector {
         friend class senf::ppi::ForwardingRoute;
     };
 
-    /** \brief Active connector baseclass
+    /** \brief Active connector base-class
 
         An active connector is a connector which emits I/O requests. Active connectors receive
         throttling notifications. Depending on the type of connector (input or output) the
@@ -225,7 +229,7 @@ namespace connector {
         friend class PassiveConnector;
     };
 
-    /** \brief Input connector baseclass
+    /** \brief Input connector base-class
 
         An input connector receives packets. It may be either an ActiveConnector or a
         PassiveConnector. An input connector contains a packet queue. This queue enables processing
@@ -242,7 +246,7 @@ namespace connector {
                 insertion/removal properties on both ends.
 
             So probably we will use a deque. I'd like a container which keeps iterators intact on
-            isertion/deletion but I believe that list is just to expensive since every packet will
+            insertion/deletion but I believe that list is just to expensive since every packet will
             be added to the queue before it can be processed.
      */
     class InputConnector 
@@ -287,7 +291,7 @@ namespace connector {
         friend class OutputConnector;
     };
     
-    /** \brief Output connector baseclass
+    /** \brief Output connector base-class
         
         An output connector sends out packets. It may be either an ActiveConnector or a
         PassiveConnector. An output connector does \e not have an built-in queueing, it relies on
index 3a2f254..6b445b4 100644 (file)
 namespace senf {
 namespace ppi {
 
-    /** \brief
+    /** \brief Manually triggered event
+
+        DebugEvent is a manually triggered event. The event is triggered by explicit calls to
+        trigger() and not by the event infrastructure.
       */
     class DebugEvent
         : public EventImplementation<>
@@ -57,7 +60,7 @@ namespace ppi {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        void trigger();
+        void trigger();                 ///< Trigger event
 
     protected:
 
diff --git a/PPI/DebugModules.cti b/PPI/DebugModules.cti
new file mode 100644 (file)
index 0000000..7e65003
--- /dev/null
@@ -0,0 +1,69 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief DebugModules inline template implementation */
+
+//#include "DebugModules.ih"
+
+// Custom includes
+#include "Utils/hexdump.hh"
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::module::debug::LogWriter<Stream,Area,level>
+
+template <class Stream, class Area, senf::log::Level level>
+prefix_ senf::ppi::module::debug::LogWriter<Stream,Area,level>::LogWriter()
+{
+    noroute(input);
+    input.onRequest(&LogWriter::request);
+}
+
+////////////////////////////////////////
+// private members
+
+template <class Stream, class Area, senf::log::Level level>
+prefix_ void senf::ppi::module::debug::LogWriter<Stream,Area,level>::request()
+{
+    Packet packet (input());
+    SENF_LOG_BLOCK((Stream)(Area)(level)({
+        packet.dump(log);
+        hexdump(packet.last().data().begin(), packet.last().data().end(),log);
+    }));
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index ad76884..296dfc5 100644 (file)
 #include "Packets/Packets.hh"
 #include "Module.hh"
 #include "ActiveFeeder.hh"
+#include "Utils/Logger.hh"
 
 //#include "DebugModules.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
-/** \namespace senf::ppi::module::debug
-    \brief Debug modules
-
-    This namespace collects several modules helpful for PPI debugging. The modules allow to manually
-    pass packets into a network and read back the output packets.
-
-    
- */
-
 namespace senf {
 namespace ppi {
 namespace module {
 namespace debug {
     
-    /** \brief
+    /** \namespace senf::ppi::module::debug
+        \brief Debug modules
+
+        This namespace collects several modules helpful for PPI debugging. The modules allow to
+        manually pass packets into a network and read back the output packets.
+
+        There are three categories of modules:
+    
+        \li <i>Active modules</i> (ActiveSource, ActiveSink) are triggered by external
+            calls. Calling \c submit() / \c request() will send the request into the module network
+            synchronously. From this it follows, that senf::ppi::run() should \e not be
+            called. Instead senf::ppi::init() is used to initialize the network and explicit calls
+            to the active debug modules drive the execution.
+        \li <i>Passive modules</i> (PassiveSource, PassiveSink) contain a queue to save packets
+            (either packets to be transmitted or packets received) and are driven by the network.
+        \li <i>Feeder (almost-)modules</i> (ActiveFeederSource, ActiveFeederSink) are a hybrid of
+            both types of modules: They contain a packet queue but actively drive the network and
+            are used together with senf::ppi::run(). senf::ppi::run() will automatically terminate
+            if all available packets have been processed. These are not modules, they are
+            collections combining a passive debug module and a senf::ppi::ActiveFeeder.
+     */
+
+    /** \brief Debug packet source with active output
+
+        This module provides packets into the network. Each call to submit() will process the packet
+        synchronously.
+
+        \note This module should not be used together with senf::ppi::run(). Instead use
+            senf::ppi::init() and explicit submit() calls. It follows, that <em>no events will be
+            signaled in the network</em>.
      */
     class ActiveSource
         : public Module, 
@@ -63,11 +84,18 @@ namespace debug {
 
         ActiveSource();
 
-        void submit(Packet packet);
+        void submit(Packet packet);     ///< Submit packet
+                                        /**< \pre boolean_test() is \c true */
 
-        bool boolean_test() const;
+        bool boolean_test() const;      ///< \c true if \a output is not throttled
     };
 
+    /** \brief Debug packet source with passive output
+        
+        This module provides a queue of packets for reading by the network. Each submit() call adds
+        a packet to the queue which will be sent into the network when requested. The output is
+        automatically throttled when the queue becomes empty.
+     */
     class PassiveSource
         : public Module
     {
@@ -78,14 +106,14 @@ namespace debug {
     public:
         typedef Queue::size_type size_type;
         
-        PassiveSource();
-        
         connector::PassiveOutput output;
+
+        PassiveSource();
         
-        void submit(Packet packet);
+        void submit(Packet packet);     ///< Enqueue packet
 
-        bool empty();
-        size_type size();
+        bool empty();                   ///< \c true if queue is empty
+        size_type size();               ///< Number of packets in queue
 
     private:
         void request();
@@ -93,7 +121,16 @@ namespace debug {
         
         Queue packets_;
     };
+    
+    /** \brief Debug packet sink with active input
 
+        This module requests packets from the network. Each call to request() will pass a packet
+        request into the network.
+
+        \note This module should not be used together with senf::ppi::run(). Instead use
+            senf::ppi::init() and explicit request() calls. It follows, that <em>no events will be
+            signaled in the network</em>.
+     */
     class ActiveSink
         : public Module,
           public SafeBool<ActiveSink>
@@ -105,11 +142,17 @@ namespace debug {
 
         ActiveSink();
 
-        Packet request();
+        Packet request();               ///< Request packet
+                                        /**< \pre boolean_test() is \c true */
 
-        bool boolean_test() const;
+        bool boolean_test() const;      ///< \c true, if \a input is not throttled
     };
 
+    /** \brief Debug packet sink with passive input
+
+        This module provides a queue for the network to write packets into. The packets can then
+        later be analyzed.
+     */
     class PassiveSink
         : public Module
     {
@@ -125,15 +168,15 @@ namespace debug {
         
         PassiveSink();
 
-        bool empty();
-        size_type size();
-        iterator begin();
-        iterator end();
+        bool empty();                   ///< \c true, if queue is empty
+        size_type size();               ///< number of packets in the queue
+        iterator begin();               ///< begin iterator of packets in the queue
+        iterator end();                 ///< past-the-end iterator of packets in the queue
 
-        Packet front();
-        Packet pop_front();
+        Packet front();                 ///< first packet in the queue
+        Packet pop_front();             ///< remove and return first packet in the queue
 
-        void clear();
+        void clear();                   ///< clear the queue
 
     private:
         void request();
@@ -141,6 +184,20 @@ namespace debug {
         Queue packets_;
     };
 
+    /** \brief Active, queue-based packet source
+        
+        The ActiveFeederSource contains a packet queue containing the packets to be precessed. These
+        packets are actively fed into the network when it is run with senf::ppi::run() until it is
+        empty, when senf::ppi::run() will return.
+
+        \note senf::ppi::run will return as soon as no events are active. If want you want is to
+            precess a set of packets placed into the ActiveFeederSource queue you must make sure,
+            that eventually all events in the module are disabled by throttling or other
+            activities. Otherwise, senf::ppi::run() will \e not return.
+
+        ActiveFeederSource is not a module but a collection of two modules: a PassiveSource and an
+        ActiveFeeder.
+     */
     class ActiveFeederSource
     {
     private:
@@ -154,11 +211,25 @@ namespace debug {
 
         ActiveFeederSource();
 
-        void submit(Packet packet);
-        bool empty();
-        size_type size();
+        void submit(Packet packet);     ///< enqueue packet
+        bool empty();                   ///< \c true, if queue is empty
+        size_type size();               ///< number of packets in the queue
     };
 
+    /** \brief Active, queue-based packet sink
+    
+        The ActiveFeederSink contains a packet queue to receive the packets from the network. The
+        ActiveFeederSink will actively request packets from the network until it's input is
+        throttled.
+
+        \note ActiveFeederSink does \e not have a termination condition like ActiveFeederSource, it
+            relies on the network to throttle it's input. Also, the same not as for
+            ActiveFeederSource applies here too: You need to ensure, that no events are active
+            eventually or senf::ppi::run will not return.
+
+        ActiveFeederSink is not a module but a collection of two modules: a PassiveSink and an
+        ActiveFeeder. 
+     */
     class ActiveFeederSink
     {
     private:
@@ -183,13 +254,35 @@ namespace debug {
 
         void clear();
     };
+   
+    /** \brief Log received packets
+
+        This module will log all packets sent to it's input using SENF_LOG to the given log
+        \a Stream, \a Area and \a level.
+     */
+    template < class Stream           = log::Debug, 
+               class Area             = log::DefaultArea, 
+               senf::log::Level level = log::VERBOSE >
+    class LogWriter
+        : public module::Module
+    {
+        SENF_PPI_MODULE(LogWriter);
+    public:
+
+        connector::PassiveInput input;
+
+        LogWriter();
+
+    private:
+        void request();
+    };
 
 }}}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "DebugModules.cci"
 //#include "DebugModules.ct"
-//#include "DebugModules.cti"
+#include "DebugModules.cti"
 #endif
 
 \f
index 1f6f668..60cb8e8 100644 (file)
 //#include "DebubgModules.test.hh"
 //#include "DebubgModules.test.ih"
 
+
 // Custom includes
 #include <algorithm>
+#include <sstream>
+
+#define _senf_LOG_STREAM logstream
+namespace {
+    std::stringstream logstream;
+}
+
 #include "Packets/Packets.hh"
 #include "DebugModules.hh"
 #include "Setup.hh"
@@ -97,9 +105,7 @@ BOOST_AUTO_UNIT_TEST(activeFeederSource)
     debug::PassiveSink sink;
 
     ppi::connect(source,sink);
-
     source.submit(senf::DataPacket::create());
-    
     ppi::run();
 
     BOOST_CHECK( source.empty() );
@@ -113,9 +119,7 @@ BOOST_AUTO_UNIT_TEST(activeFeederSink)
     debug::ActiveFeederSink sink;
 
     ppi::connect(source,sink);
-
     source.submit(senf::DataPacket::create());
-    
     ppi::run();
 
     BOOST_CHECK( ! sink.empty() );
@@ -128,6 +132,20 @@ BOOST_AUTO_UNIT_TEST(activeFeederSink)
     BOOST_CHECK( source.empty() );
 }
 
+BOOST_AUTO_UNIT_TEST(logWriter)
+{
+    debug::ActiveFeederSource source;
+    debug::LogWriter<> sink;
+
+    ppi::connect(source,sink);
+    senf::PacketData::byte data[] = { 0x13u, 0x24u, 0x35u };
+    source.submit( senf::DataPacket::create(data) );
+    senf::ppi::run();
+    
+    BOOST_CHECK_EQUAL( logstream.str(), 
+                       "  0000  13 24 35                                          .$5\n\n" );
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 2df295f..482d17b 100644 (file)
 namespace senf {
 namespace ppi {
 
-    /** \brief
+    /** \brief Event registry and control
+
+        The EventManager control event registration and manages global event parameters. The
+        EventManager controls event dispatch but does \e not control event generation. This is the
+        responsibility of an external component (the Scheduler)
       */
     class EventManager
     {
@@ -47,16 +51,13 @@ namespace ppi {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
-        template <class Descriptor>
 #ifndef DOXYGEN
+        // Somehow doxygen barfs on this definition
+        template <class Descriptor>
         struct Callback
-#else
-        // This is SO stupid but doxygen must have some scoping problems if the 
-        // struct is called 'Callback' and will hang in an endless loop somewhere
-        struct Callback_
-#endif
             : public detail::Callback<typename Descriptor::EventArg>
         {};
+#endif
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -74,17 +75,17 @@ namespace ppi {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
+        ClockService::clock_type now(); ///< Current time at last event dispatch
+        ClockService::clock_type time(); ///< Expected time of the last event
+
+    protected:
+
+    private:
         template <class Descriptor>
         void registerEvent(module::Module & module,
                            typename Callback<Descriptor>::type callback,
                            Descriptor & descriptor);
 
-        ClockService::clock_type now();
-        ClockService::clock_type time();
-
-    protected:
-
-    private:
         void destroyModule(module::Module & module);
 
         typedef boost::ptr_vector<detail::EventBindingBase> EventRegistrations;
index 1b99c4b..6f9c9c9 100644 (file)
@@ -43,10 +43,9 @@ namespace ppi {
     // 'callback()' will access the EventBinding wrapper to find the user-callback to signal. It
     // will do any needed internal processing, call that user callback and clean up afterwards.
 
-    /** \brief Generic event interface baseclass
+    /** \brief Generic event interface base-class
 
-        The EventDescriptor baseclass provides an interface to manipulate events in a generic
-        way. This allows to register events or to temporarily disable event processing.
+        The EventDescriptor base-class provides an interface to control events.
      */ 
     class EventDescriptor
     {
@@ -78,6 +77,8 @@ namespace ppi {
         friend class ForwardingRoute;
     };
     
+    /** \brief Internal: Callback forwarders
+     */
     template <class EventType, class Self>
     class EventImplementationHelper
     {
@@ -85,7 +86,13 @@ namespace ppi {
         typedef typename detail::EventArgType<EventType>::type EventArg;
 
         void callback(EventArg event, ClockService::clock_type time);
-        void callback(EventArg event);
+                                        ///< Forward event to user callback
+                                        /**< \param[in] event Event argument to pass to the user
+                                             callback
+                                             \param[in] time Expected time of the event */
+        void callback(EventArg event);  ///< Forward event to user callback
+                                        /**< \param[in] event Event argument to pass to the user
+                                             callback. */
 
     private:
         detail::EventBinding<EventType> & binding();
@@ -106,6 +113,43 @@ namespace ppi {
 
 #endif
 
+    /** \brief Event implementation base class
+
+        EventImplementation provides the base-class for all Event implementations. 
+        \code
+        class SomeEvent : public EventImplementation<SomeEventArg>
+        {
+        public:
+            SomeEvent() {}
+
+        private:
+            virtual void v_enable() {
+                // register cb() to be called when the event occurs
+            }
+
+            virtual void v_disable() {
+                // unregister cb()
+            }
+
+            void cb() {
+                // Build event argument
+                SomeEventArg arg (...); 
+                // Call the event callback
+                callback(arg);
+            }
+        };
+        \endcode
+
+        Every event needs to implement v_enable() and v_disable(). v_enable() should register some
+        member (in the example \c cb() ) to be called whenever the event occurs, while v_disable()
+        should unregister it.
+
+        The \a EventType argument to EventImplementation defines the type of argument passed to the
+        user callback. It defaults to \c void. . This user callback is called from within the
+        registered member (e.g. \c cb() ) by calling the inherited callback() member. This member
+        takes an \a EventType reference as argument which will be forwarded to the user callback. If
+        available, you should also provide the \e expected event time as a second argument.
+     */
     template <class EventType>
     class EventImplementation
         : public EventDescriptor, 
@@ -115,8 +159,8 @@ namespace ppi {
         typedef EventType Event;
         typedef typename detail::EventArgType<EventType>::type EventArg;
 
-        module::Module & module() const;
-        EventManager & manager() const;
+        module::Module & module() const; ///< Module in which the event is registered
+        EventManager & manager() const; ///< EventManager of the event
         
     protected:
         EventImplementation();
index 1e342a0..d23e780 100644 (file)
@@ -34,14 +34,14 @@ namespace senf {
 namespace ppi {
 namespace detail {
 
+#ifndef DOXYGEN
+
     template <class EventType>
     struct EventArgType
     {
         typedef EventType const & type;
     };
 
-#ifndef DOXYGEN
-
     template <>
     struct EventArgType<void>
     {
index 9157622..f750530 100644 (file)
 namespace senf {
 namespace ppi {
 
+    /** \brief IOEvent event information
+
+        Information passed to the IOEvent event handler
+     */
     struct IOEventInfo
     {
-        unsigned events;
+        unsigned events;                ///< Type of event signaled
+                                        /**< The value is a combination of the flags from
+                                             IOEvent::EventFlags */
     };
 
-    /** \brief
+    /** \brief FileHandle based I/O read/write event
+
+        An IOEvent is signaled, whenever the FileHandle \a handle becomes readable or writable. The
+        type of event is specified using the \a events mask with values from EventFlags.
 
         \fixme Implement error/EOF handling
       */
index 3064380..1b7fc2d 100644 (file)
 namespace senf {
 namespace ppi {
 
+    /** \brief Continually signaled event
+
+        An IdleEvent is signaled continually and repeatedly while enabled. It will consume 100% of
+        available CPU resources. The resource usage is controlled by adequate event throttling.
+     */
     class IdleEvent
         : public EventImplementation<>
     {
index cfb0631..798729a 100644 (file)
 namespace senf {
 namespace ppi {
 
+    /** \brief IntervalTimer event information
+
+        Information passed to the IntervalTimer event handler
+     */
     struct IntervalTimerEventInfo
     {
-        ClockService::clock_type expected;
-        ClockService::clock_type intervalStart;
-        unsigned number;
+        ClockService::clock_type expected; ///< Scheduled event time
+        ClockService::clock_type intervalStart; ///< Start of the current time interval
+        unsigned number;                ///< Number of the current event within the interval
     };
 
-    /** \brief
+    /** \brief High precision regularly signaled event.
+
+        An IntervalTimer signals an event \a eventsPerInterval times each \a interval
+        nanoseconds. The event counter and timer are reset, whenever the event is disabled.
       */
     class IntervalTimer
         : public EventImplementation<IntervalTimerEventInfo>
index 861decf..2cd9212 100644 (file)
     \section class_diagram Class Diagram
 
     \image html classes.png
+
+    \fixme Implement Spliters: PassiveSplitter, PrioritySplitter, CloneSplitter
+    \fixme Implement DiscardSink, CloneSource
  */
 
 \f
index 4b4323c..231b045 100644 (file)
@@ -39,9 +39,9 @@ namespace senf {
 namespace ppi {
 namespace module {
 
-    /** \brief Module baseclass
+    /** \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 +49,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 +175,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,10 +188,11 @@ 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 time() const; ///< Time-stamp of the currently processing event
+                                        /**< If available, this returns the scheduled time of the
+                                             event. */
 
-        ClockService::clock_type now() const;
+        ClockService::clock_type now() const; ///< Current time of the currently processing event
 
 #ifndef DOXYGEN
         virtual void macro_SENF_PPI_MODULE_missing() = 0;
index 697fa7b..3386687 100644 (file)
@@ -33,6 +33,8 @@ namespace ppi {
 namespace module {
 namespace detail {
 
+#ifndef DOXYGEN
+
     // Placing these into a class simplifies the friend declaration
     template <class Source, class Target>
     struct RouteHelper 
@@ -50,6 +52,8 @@ namespace detail {
                           EventDescriptor &,
                           connector::OutputConnector &);
     };
+
+#endif
        
 }}}}
 
index bda5e66..25c771e 100644 (file)
@@ -45,6 +45,8 @@ prefix_ void senf::ppi::ModuleManager::init()
         (*i)->init();
 }
 
+#ifndef DOXYGEN
+
 struct senf::ppi::ModuleManager::RunGuard
 {
     RunGuard(ModuleManager & m) : manager(m) { manager.running_ = true; }
@@ -52,6 +54,8 @@ struct senf::ppi::ModuleManager::RunGuard
     ModuleManager & manager;
 };
 
+#endif
+
 prefix_ void senf::ppi::ModuleManager::run()
 {
     init();
index 843562b..b944123 100644 (file)
@@ -70,8 +70,10 @@ namespace ppi {
 
         typedef std::vector<module::Module *> ModuleRegistry;
 
+#ifndef DOXYGEN
         struct RunGuard;
         friend class RunGuard;
+#endif
 
         ModuleRegistry moduleRegistry_;
         bool running_;
index 88722c2..307d341 100644 (file)
 namespace senf {
 namespace ppi {
 
+    /** \brief Routing base class
+
+        Routing information is defined within each module to define the control flow. RouteBase is
+        the generic base class for all routing entries.
+     */
     class RouteBase
     {
     public:
@@ -46,11 +51,17 @@ namespace ppi {
         module::Module * module_;
     };
 
+    /** \brief Forwarding route base class
+
+        All routes which may forward control information are based on
+        ForwardingRoute. ForwardingRoute provides methods to control and query the throttling
+        behavior.
+     */
     class ForwardingRoute
         : public RouteBase
     {
     public:
-        bool autoThrottling() const;
+        bool autoThrottling() const;    ///< Query current autoThrottling state
         void autoThrottling(bool state); ///< Change automatic throttle notification forwarding
                                         /**< By default, throttle notifications are automatically
                                              forwarded from active to passive connectors. This may
@@ -66,7 +77,10 @@ namespace ppi {
 
                                              \param[in] state New throttle forwarding state */
 
-        bool throttled() const;
+        bool throttled() const;         ///< \c true, if the route is throttled
+                                        /**< This member checks only the automatic throttling
+                                             state. If autoThrottling() is \c false, this member
+                                             will always return \c false. */
         
     protected:
         ForwardingRoute(module::Module & module);
@@ -104,13 +118,17 @@ namespace ppi {
         
         Route instances are created by Module::route statements. The Route class provides an
         interface to manipulate the flow processing.
+
+        The concrete interface provided depends on the type of route. If the route is a forwarding
+        route, it will be based on ForwardingRoute otherwise it will be based directly on
+        RouteBase.
      */
     template <class Source, class Target>
     class Route
         : public detail::RouteImplementation<Source,Target>
     {
-        typedef detail::RouteImplementation<Source,Target> Base;
     private:
+        typedef detail::RouteImplementation<Source,Target> Base;
         typedef detail::RouteImplementation<Source,Target> Implementation;
         
         Route(module::Module & module, Source & source, Target & target);
index 7637d3e..46b7e8a 100644 (file)
@@ -35,6 +35,8 @@
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
+#ifndef DOXYGEN
+
 namespace senf {
 namespace ppi {
 namespace detail {
@@ -59,8 +61,6 @@ namespace detail {
         typedef Connector type;
     };
 
-#ifndef DOXYGEN
-
     // RoutingTraits specialization for Event types. Events may be both dataSource or dataTarget but
     // cannot be notifySource.
     template <class Event>
@@ -75,8 +75,6 @@ namespace detail {
         typedef EventDescriptor type;
     };
 
-#endif
-    
     // The RoutingTraits give routing related information about the argument type:
     //  - Wether the type is a notifySource or notifyTarget
     //  - Wether the type is dataSource or dataTarget
@@ -203,6 +201,8 @@ namespace detail {
 
 }}}
 
+#endif
+
 ///////////////////////////////ih.e////////////////////////////////////////
 #endif
 
index 5c0ca9e..f416c0d 100644 (file)
@@ -81,11 +81,16 @@ namespace module {
           class SomeReader
           {
           public:
-              typedef unspecified_type Handle;        // type of handle requested
-              SomeReader();                           // default constructible
-              Packet::ptr operator()(Handle handle);  // extraction function
+              typedef unspecified_type Handle;   // type of handle requested
+              SomeReader();                      // default constructible
+              Packet operator()(Handle handle);  // extraction function
           };
         \endcode
+        
+        Whenever the FileHandle object is ready for reading, the \a Reader's \c operator() is called
+        to read a packet. The default \a Reader is \c PacketReader<>, which will read packets from a
+        datagram SocketHandle into DataPacket's. You may 
+        
      */
     template <class Reader=PacketReader<> >
     class ActiveSocketReader 
index e60ab58..05ade30 100644 (file)
@@ -38,6 +38,7 @@ namespace senf {
 namespace ppi {
 namespace detail {
 
+    /** \brief Internal: Association Event - Module - Handler, base-class */
     class EventBindingBase
     {
     public:
@@ -60,6 +61,8 @@ namespace detail {
         friend class senf::ppi::EventManager;
     };
 
+    /** \brief Internal: Callback forwarders
+     */
     template <class EventType, class Self>
     class EventBindingHelper
     {
@@ -88,6 +91,7 @@ namespace detail {
 
 #endif
 
+    /** \brief Internal: Association Event - Module - Handler, event type specific */
     template <class EventType>
     class EventBinding
         : public EventBindingBase, 
index 8fb57dd..92c0546 100644 (file)
@@ -43,6 +43,8 @@ namespace ppi {
     class QueueingDiscipline;
     class ModuleManager;
 
+#ifndef DOXYGEN
+
     namespace detail {
         class EventBindingBase;
         template <class EvImpl> class EventBinding;
@@ -58,6 +60,8 @@ namespace ppi {
             class RouteImplementation;
     }
 
+#endif
+
     namespace module {       
         class Module;       
         namespace detail {
index 99880a8..c766392 100644 (file)
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
+namespace log {
 
 #   ifndef _senf_LOG_STREAM
 #     define _senf_LOG_STREAM std::cerr
@@ -181,7 +182,7 @@ namespace senf {
 
         \hideinitializer
      */
-#   define SENF_LOG_DEF_AREA(area)
+#   define SENF_LOG_DEF_AREA(area) struct area {}
 
     /** \brief Define log stream
 
@@ -190,7 +191,7 @@ namespace senf {
 
         \hideinitializer
      */
-#   define SENF_LOG_DEF_STREAM(stream)
+#   define SENF_LOG_DEF_STREAM(stream) struct stream {}
 
     /** \brief Define log parameter alias
 
@@ -199,11 +200,16 @@ namespace senf {
 
         \hideinitializer
      */
-#   define SENF_LOG_DEF_ALIAS(alias,args)
+#   define SENF_LOG_DEF_ALIAS(alias,args) struct alias {}
 
     /// @}
 
-}
+    enum Level { VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL };
+    
+    SENF_LOG_DEF_STREAM(Debug);
+    SENF_LOG_DEF_AREA(DefaultArea);
+
+}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 //#include "Logger.cci"
index 362d243..8fec9c3 100644 (file)
--- a/senf.dict
+++ b/senf.dict
@@ -1,18 +1,28 @@
 acceptfrom
 accessor
+ActiveConnector
+ActiveFeeder
+ActiveFeederSink
+ActiveFeederSource
+ActiveInput
+ActiveOutput
+ActiveSink
+ActiveSource
 addr
 AddressingPolicy
 AddressingPolicyBase
 addtogroup
 aListCollection
 alloc
+arg
 async
+autoThrottling
 aVectorCollection
 BaseParser
 berlios
 bitfield
 bund
-Callback
+callback
 callbacks
 cb
 cerr
@@ -29,9 +39,11 @@ createBefore
 DataPacket
 dd
 de
+DebugModules
 DefaultBundle
 defaultInit
 defgroup
+deque
 dil
 DNS
 dontinclude
@@ -47,6 +59,12 @@ ethertype
 EthVLan
 EUI
 EUID
+EventBinding
+EventDescriptor
+EventImplementation
+EventManager
+eventsPerInterval
+EventType
 ExampleListPolicy
 ExampleVectorPolicy
 ExtendedParser
@@ -59,6 +77,7 @@ findPrev
 fixme
 fokus
 FooParser
+ForwardingRoute
 fraunhofer
 fuer
 GlobalScope
@@ -72,6 +91,7 @@ htm
 html
 http
 IANA
+IdleEvent
 ih
 impl
 INet
@@ -80,10 +100,13 @@ init
 initHeadSize
 initSize
 inline
+InputConnector
 Institut
 Int
+IntervalTimer
 IntField
 InvalidPacketChainException
+IOEvent
 ip
 IpV
 ipv
@@ -111,15 +134,21 @@ nextPacketType
 NIS
 NoAddressingPolicy
 noinit
+noroute
 nothrow
 offene
 Ok
+onRequest
+onThrottle
+onUnthrottle
 Ooops
 org
 os
 ostream
 OtherPacket
 OtherPacketType
+OutputConnector
+outputRequest
 OverlayField
 PacketData
 PacketImpl
@@ -146,12 +175,21 @@ ParseListB
 ParseListN
 parseNextAs
 ParseVec
+PassiveConnector
+PassiveInput
+PassiveOutput
+PassiveSink
+PassiveSource
 png
+ppi
 pre
 prev
 protocolbundle
 protocolbundles
+QueueingDiscipline
+queueSize
 refcount
+registerEvent
 registerPacket
 registerPacketType
 registerSomePacket
@@ -174,7 +212,10 @@ SiteScope
 SizeParser
 skipline
 SocketHandle
+SomeEvent
+SomeEventArg
 someField
+SomeModule
 someOtherField
 SomePacket
 SomePacketParser
@@ -192,6 +233,7 @@ SyntaxException
 SystemException
 td
 templated
+ThresholdQueueing
 todo
 tr
 TruncatedPacketException
@@ -203,6 +245,9 @@ UDPPacket
 UInt
 UIntField
 unicast
+unthrottle
+unthrottles
+unthrottling
 VectorN
 vlanId
 VLanId