X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=PPI%2FConnectors.hh;h=1b7e5403fd2f91525fdf5539719854d73a2fad07;hb=2246ca853064965a7b263c49597c4e74397b989b;hp=1b299e2337c2bd933663e885445007e6aabb2ef4;hpb=89efe5f504c400212090aba703c7ee385f483c64;p=senf.git diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index 1b299e2..1b7e540 100644 --- a/PPI/Connectors.hh +++ b/PPI/Connectors.hh @@ -1,6 +1,8 @@ +// $Id$ +// // Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -19,40 +21,58 @@ // 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. + \brief Connectors public header */ - 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 +#ifndef HH_Connectors_ +#define HH_Connectors_ 1 // Custom includes +#include #include - -//#include "Conenctors.mpp" +#include +#include "../Utils/safe_bool.hh" +#include "../Packets/Packets.hh" +#include "predecl.hh" +#include "detail/Callback.hh" +#include "Queueing.hh" + +//#include "Connectors.mpp" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { namespace ppi { +namespace connector { - ///@{ - ///\addtogroup connectors + /** \namespace senf::ppi::connector + \brief Connector classes - /** \brief Connector baseclass + 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: + \li senf::ppi::connector::ActiveInput + \li senf::ppi::connector::ActiveOutput + \li senf::ppi::connector::PassiveInput + \li senf::ppi::connector::PassiveOutput. + + Connectors are declared as module data members and are then externally connected to other + modules. + + \see + senf::ppi::module::Module \n + senf::ppi::connect() + \ref ppi_connectors + */ + + /** \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 @@ -62,16 +82,25 @@ namespace ppi { : boost::noncopyable { public: - Connector & peer(); ///< Get peer connected to this connector - Module & module(); ///< Get this connectors containing module + Connector & peer() const; ///< Get peer connected to this connector + module::Module & module() const; ///< Get this connectors containing module protected: - // here to protect Connector(); - ~Connector(); + virtual ~Connector(); + + void connect(Connector & target); + + private: + void setModule(module::Module & module); + + Connector * peer_; + module::Module * module_; + + 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 @@ -105,24 +134,47 @@ namespace ppi { operation is to be performed. */ - bool throttled(); ///< Get accumulative throttling state - bool nativeThrottled(); ///< Get native throttling state + bool throttled() const; ///< Get accumulative throttling state + bool nativeThrottled() const; ///< 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(); + ActiveConnector & peer() const; protected: - // here to protect PassiveConnector(); - ~PassiveConnector(); + + void emit(); + + private: + // Called by the routing to change the remote throttling state + 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(); + void emitUnthrottle(); + + // Called after unthrottling the connector + virtual void v_unthrottleEvent(); + + // called by ForwardingRoute to register a new route + void registerRoute(ForwardingRoute & route); + + typedef detail::Callback<>::type Callback; + Callback callback_; + + bool remoteThrottled_; + bool nativeThrottled_; + + typedef std::vector Routes; + Routes routes_; + + 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 @@ -135,9 +187,10 @@ namespace ppi { class ActiveConnector : public virtual Connector { + typedef detail::Callback<>::type Callback; public: template - void onThrottle(Handler); ///< Register throttle notification handler + void onThrottle(Handler 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 @@ -147,9 +200,10 @@ namespace ppi { \param[in] handler Handler to call on throttle notifications. */ + void onThrottle(); ///< Clear throttle notification handler template - void onUnthrottle(Handler); ///< Register unthrottle notification handler + void onUnthrottle(Handler 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 @@ -159,16 +213,34 @@ namespace ppi { \param[in] handler Handler to call on unthrottle notifications. */ + void onUnthrottle(); ///< Clear unthrottle notification handler - PassiveConnector & peer(); + bool throttled() const; ///< \c true, if peer() is throttled + + PassiveConnector & peer() const; protected: - // here to protect - PassiveConnector(); - ~PassiveConnector(); + ActiveConnector(); + + private: + // called by the peer() to forward throttling notifications + void notifyThrottle(); + void notifyUnthrottle(); + + // called by ForwardingRoute to register a new route + void registerRoute(ForwardingRoute & route); + + Callback throttleCallback_; + Callback unthrottleCallback_; + + typedef std::vector NotifyRoutes; + NotifyRoutes notifyRoutes_; + + friend class senf::ppi::ForwardingRoute; + 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 @@ -185,17 +257,19 @@ namespace ppi { 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 : public virtual Connector { + typedef std::deque Queue; public: - typedef unspecified queue_iterator; ///< Iterator type of the embedded queue - typedef unspecified size_type; ///< Unsigned type representing the number of queue elements + typedef Queue::const_iterator queue_iterator; ///< Iterator type of the embedded queue + typedef Queue::size_type size_type; ///< Unsigned type for counting queue elements - Packet::ptr operator(); ///< Get a packet + + Packet 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 @@ -204,40 +278,34 @@ namespace ppi { 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 */ + Packet read(); ///< Alias for operator()() - OutputConnector & peer(); + OutputConnector & peer() const; - 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 + queue_iterator begin() const; ///< Access queue begin (head) + queue_iterator end() const; ///< Access queue past-the-end (tail) + Packet peek() const; ///< Return head element from the queue - size_type queueSize(); ///< Return number of elements in the queue - bool empty(); ///< Return queueSize() == 0 + size_type queueSize() const; ///< Return number of elements in the queue + bool empty() const; ///< Return queueSize() == 0 protected: - // here to protect - PassiveConnector(); - ~PassiveConnector(); + InputConnector(); + + private: + void enqueue(Packet p); + + virtual void v_requestEvent(); + virtual void v_enqueueEvent(); + virtual void v_dequeueEvent(); + + Queue queue_; + + 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 @@ -247,77 +315,104 @@ namespace ppi { : public virtual Connector { public: - void operator(Packet::ptr); ///< Send out a packet + void operator()(Packet p); ///< Send out a packet - InputConnector & peer(); + void write(Packet p); ///< Alias for operator()(Packet p) + + InputConnector & peer() const; protected: - // here to protect - PassiveConnector(); - ~PassiveConnector(); + OutputConnector(); }; - + /** \brief Combination of PassiveConnector and InputConnector - In addition to the native and the forwarded throttling state, the PassiveInput manages a - queue throttling state. This state is automatically managed by a queueing discipline. The - standard queueing discipline is ThresholdQueueing, which throttles the connection whenever - the queue length reaches the high threshold and unthrottles the connection when the queue - reaches the low threshold. The default queueing discpiline is + The PassiveInput automatically controls the connectors throttling state using a queueing + discipline. The standard queueing discipline is ThresholdQueueing, which throttles the + connection whenever the queue length reaches the high threshold and unthrottles the + connection when the queue reaches the low threshold. The default queueing discipline is ThresholdQueueing(1,0) which will throttle the input whenever the queue is non-empty. */ class PassiveInput - : public PassiveConnector, public InputConnector + : public PassiveConnector, public InputConnector, + public safe_bool { public: - ActiveOutput & peer(); + PassiveInput(); + + ActiveOutput & peer() const; - template - void qdisc(QueueingDiscipline const & disc); ///< Change the queueing discipline + bool boolean_test() const; ///< \c true, if ! empty() + + template + void qdisc(QDisc const & disc); ///< Change the queueing discipline /**< The queueing discipline is a class which provides the QueueingDiscipline interface. \param[in] disc New queueing discipline */ + + private: + void v_enqueueEvent(); + void v_dequeueEvent(); + void v_unthrottleEvent(); + + boost::scoped_ptr qdisc_; }; /** \brief Combination of PassiveConnector and OutputConnector */ class PassiveOutput - : public PassiveConnector, public OutputConnector + : public PassiveConnector, public OutputConnector, + public safe_bool { public: - ActiveInput & peer(); + ActiveInput & peer() const; + + bool boolean_test() const; ///< Always \c true + + void connect(ActiveInput & target); ///< Internal: Use senf::ppi::connect() instead + + friend class ActiveInput; }; /** \brief Combination of ActiveConnector and InputConnector */ class ActiveInput - : public ActiveConnector, public InputConnector + : public ActiveConnector, public InputConnector, + public safe_bool { public: - PassiveOutput & peer(); + PassiveOutput & peer() const; + + bool boolean_test() const; ///< \c true, if ! empty() or ! throttled() + + void request(); ///< request more packets without dequeuing any packet - void request(); ///< request more packets without dequeing any packet + private: + void v_requestEvent(); }; /** \brief Combination of ActiveConnector and OutputConnector */ class ActiveOutput - : public ActiveConnector, public OutputConnector + : public ActiveConnector, public OutputConnector, + public safe_bool { public: - ActiveInput & peer(); - }; + PassiveInput & peer() const; + + bool boolean_test() const; ///< \c true if peer() is ! throttled() - ///@} + void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead + }; -}} +}}} ///////////////////////////////hh.e//////////////////////////////////////// -//#include "Conenctors.cci" -//#include "Conenctors.ct" -//#include "Conenctors.cti" +#include "Connectors.cci" +//#include "Connectors.ct" +#include "Connectors.cti" #endif @@ -327,4 +422,6 @@ namespace ppi { // c-file-style: "senf" // indent-tabs-mode: nil // ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// comment-column: 40 // End: