Skip to content
Snippets Groups Projects
Connectors.hh 12.6 KiB
Newer Older
// 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 Conenctors public header */

/** \defgroup connectors Connector classes

    A connector has two independent properties
    \li it may be \e active or \e passive
    \li it may be an \e input or an \e output
    
    \e Active connectors are activated from within the module, \e passive connectors are signaled by
    the external framework. \e Input modules receive packets, \e output modules send packets.

    All passive connectors call some onRequest callback whenever I/O needs to be performed. All
    input modules possess a packet queue.

    We therefore have 4 connector types: senf::ppi::ActiveInput, senf::ppi::ActiveOutput,
    senf::ppi::PassiveInput and senf::ppi::PassiveOutput.
 */

#ifndef HH_Conenctors_
#define HH_Conenctors_ 1

// Custom includes
#include <boost/utility.hpp>

//#include "Conenctors.mpp"
///////////////////////////////hh.p////////////////////////////////////////

namespace senf {
namespace ppi {

    /** \brief Connector baseclass

        This connector provides access to the generic connector facilities. This includes the
        connection management (access to the connected peer) and the containment management (access
        to the containing module)
     */
    class Connector
        : boost::noncopyable
    {
    public:
        Connector & peer();             ///< Get peer connected to this connector
        Module & module();              ///< Get this connectors containing module

    protected:
        // here to protect
        Connector();
        ~Connector();
    };

    /** \brief Passive connector baseclass

        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
        of connector (output or input) the respective throttling is called forward or backward
        throttling.

        Passive connectors always handle two throttling states: 
        
        \li The \e native throttling state is set manually by the module. It is the throttling state
            originating in the current module
        \li The \e forwarded throttling state is the state as it is received by throttling
            notifications

        The accumulative throttling state is generated by combining all sub-states.

        \ingroup connectors
     */
    class PassiveConnector 
        : public virtual Connector
    {
    public:
        template <class Handler>
        void onRequest(Handler handler);///< Register I/O event handler
                                        /**< The registered handler will be called, whenever packets
                                             arrive or should be generated by the module depending
                                             on the connector type (input or output). The \a handler
                                             argument is either an arbitrary callable object or it
                                             is a pointer-to-member to a member of the class which
                                             holds this input. In the second case, the pointer will
                                             automatically be bound to the containing instance.
                                             
                                             \param[in] handler Handler to call, whenever an I/O
                                                 operation is to be performed. */

        
        bool throttled();               ///< Get accumulative throttling state
        bool nativeThrottled();         ///< Get native throttling state

        void throttle();                ///< Set native throttling
        void unthrottle();              ///< Revoke native throttling
        
        void notifyThrottle();          ///< Forward a throttling notification to this connector
        void notifyUnthrottle();        ///< Forward an unthrottling notification to this connector

        ActiveConnector & peer();

    protected:
        // here to protect
        PassiveConnector();
        ~PassiveConnector();
    };

    /** \brief Active connector baseclass

        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
        respective throttling is called forward or backward throttling.

        Active connectors do not handle any throttling state, they just receive the
        notifications. These notifications should then either be processed by the module or be
        forwarded to other connectors.

        \ingroup connectors
     */
    class ActiveConnector 
        : public virtual Connector
    {
    public:
        template <class Handler>
        void onThrottle(Handler);       ///< Register throttle notification handler
                                        /**< The handler register here will be called, whenever a
                                             throttle notification comes in. The \a handler argument
                                             is either an arbitrary callable object or it is a
                                             pointer-to-member to a member of the class which holds
                                             this input. In the second case, the pointer will
                                             automatically be bound to the containing instance.

                                             \param[in] handler Handler to call on throttle
                                                 notifications. */

        template <class Handler>
        void onUnthrottle(Handler);     ///< Register unthrottle notification handler
                                        /**< The handler register here will be called, whenever an
                                             unthrottle notification comes in. The \a handler
                                             argument is either an arbitrary callable object or it
                                             is a pointer-to-member to a member of the class which
                                             holds this input. In the second case, the pointer will
                                             automatically be bound to the containing instance.

                                             \param[in] handler Handler to call on unthrottle
                                                 notifications. */

        PassiveConnector & peer();

    protected:
        // here to protect
        PassiveConnector();
        ~PassiveConnector();
    };

    /** \brief Input connector baseclass

        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
        packets in batches or generating multiple output packets from a single input packet. The
        queues have the potential to greatly simplify the module implementations.

        \ingroup connectors
     */
    class InputConnector 
        : public virtual Connector
    {
    public:
        typedef unspecified queue_iterator; ///< Iterator type of the embedded queue
        typedef unspecified size_type;  ///< Unsigned type representing the number of queue elements

        Packet::ptr operator();         ///< Get a packet
                                        /**< This member is the primary method to access received
                                             data. On passive connectors, this operator will just
                                             dequeue a packet from the packet queue. If the
                                             connector is active, the connector will request new
                                             packets from the connected module. If the packet
                                             request cannot be fulfilled, this is considered to be a
                                             logic error in the module implementation and an
                                             exception is raised. */
        operator unspecified_boolean_type (); ///< Check packet availability
                                        /**< Using any input connector in a boolean context will
                                             check, wether an input request can be fulfilled. This
                                             is always possible if the queue is non-empty. If the
                                             input is active, it also returns when the connected
                                             passive output is not throttled so new packets can be
                                             requested. 

                                             Calling the operator() member is an error if this test
                                             returns \c false

                                             \returns \c true if operator() can be called, \c false
                                                 otherwise */
        operator ! ();                  ///< Check packet availability
                                        /**< Inverse of the boolean conversion operator
                                             \returns \c false if operator() can be called, \c true
                                                 otherwise */

        OutputConnector & peer();

        queue_iterator begin();         ///< Access queue begin (head)
        queue_iterator end();           ///< Access queue past-the-end (tail)
        Packet::ptr head();             ///< Return head element from the queue

        size_type queueSize();          ///< Return number of elements in the queue
        bool empty();                   ///< Return queueSize() == 0

    protected:
        // here to protect
        PassiveConnector();
        ~PassiveConnector();
    };
    
    /** \brief Output connector baseclass
        
        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
        the queueing of the connected input.

        \ingroup connectors
     */
    class OutputConnector 
        : public virtual Connector
    {
    public:
        void operator(Packet::ptr);     ///< Send out a packet

        InputConnector & peer();

    protected:
        // here to protect
        PassiveConnector();
        ~PassiveConnector();
    };

    /** \brief Combination of PassiveConnector and InputConnector

        \ingroup connectors
     */
    class PassiveInput 
        : public PassiveConnector, public InputConnector
    {
    public:
        ActiveOutput & peer();

        template <class QDisc>
        QDisc const & qdisc(QDisc const & disc);
    };

    /** \brief Combination of PassiveConnector and OutputConnector

        \ingroup connectors
     */
    class PassiveOutput
        : public PassiveConnector, public OutputConnector
    {
    public:
        ActiveInput & peer();
    };

    /** \brief Combination of ActiveConnector and InputConnector

        \ingroup connectors
     */
    class ActiveInput
        : public ActiveConnector, public InputConnector
    {
    public:
        void request();                 ///< request more packets without dequeing any packet

        PassiveOutput & peer();
    };

    /** \brief Combination of ActiveConnector and OutputConnector

        \ingroup connectors
     */
    class ActiveOutput
        : public ActiveConnector, public OutputConnector
    {
    public:
        ActiveInput & peer();
    };

}}

///////////////////////////////hh.e////////////////////////////////////////
//#include "Conenctors.cci"
//#include "Conenctors.ct"
//#include "Conenctors.cti"
#endif


// Local Variables:
// mode: c++
// fill-column: 100
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// End: