X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=PPI%2FConnectors.hh;h=4779c3036681867519389053c241dcfb2c46f043;hb=88b7af123f3faced1235041a506573caded251e8;hp=553ff967cb4a6071f3028de43954f0414bcb13df;hpb=026887c8f93c5dc89fb68446ae014205de559451;p=senf.git diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index 553ff96..4779c30 100644 --- a/PPI/Connectors.hh +++ b/PPI/Connectors.hh @@ -21,22 +21,6 @@ /** \file \brief Connectors 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_Connectors_ #define HH_Connectors_ 1 @@ -44,8 +28,8 @@ #include #include #include -#include "Utils/SafeBool.hh" -#include "Packets/Packets.hh" +#include "../Utils/SafeBool.hh" +#include "../Packets/Packets.hh" #include "predecl.hh" #include "detail/Callback.hh" #include "Queueing.hh" @@ -57,7 +41,36 @@ namespace senf { namespace ppi { namespace connector { - /** \brief Connector baseclass + /** \namespace senf::ppi::connector + \brief 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: + \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 @@ -67,8 +80,8 @@ namespace connector { : boost::noncopyable { public: - Connector & peer(); ///< Get peer connected to this connector - module::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: Connector(); @@ -85,7 +98,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 @@ -119,16 +132,13 @@ namespace connector { 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: PassiveConnector(); @@ -136,12 +146,33 @@ namespace connector { 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 @@ -154,9 +185,10 @@ namespace connector { class ActiveConnector : public virtual Connector { + typedef detail::Callback<>::type Callback; public: template - void onThrottle(Handler handle); ///< 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 @@ -164,11 +196,12 @@ namespace connector { this input. In the second case, the pointer will automatically be bound to the containing instance. - \param[in] handle Handler to call on throttle + \param[in] handler Handler to call on throttle notifications. */ + void onThrottle(); ///< Clear throttle notification handler template - void onUnthrottle(Handler handle); ///< 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 @@ -176,16 +209,36 @@ namespace connector { holds this input. In the second case, the pointer will automatically be bound to the containing instance. - \param[in] handle Handler to call on unthrottle + \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: 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 @@ -202,18 +255,18 @@ 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 - : public virtual Connector, - public SafeBool + : public virtual Connector { typedef std::deque Queue; public: 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 operator()(); ///< Get a packet /**< This member is the primary method to access received data. On passive connectors, this operator will just @@ -223,28 +276,17 @@ namespace connector { request cannot be fulfilled, this is considered to be a logic error in the module implementation and an exception is raised. */ - bool boolean_test (); ///< Check packet availability - /**< Using any input connector in a boolean context will - check, whether 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 + Packet read(); ///< Alias for operator()() - \returns \c true if operator() can be called, \c false - otherwise */ + OutputConnector & peer() const; - OutputConnector & peer(); + 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 - queue_iterator begin(); ///< Access queue begin (head) - queue_iterator end(); ///< Access queue past-the-end (tail) - Packet peek(); ///< 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: InputConnector(); @@ -261,7 +303,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 @@ -271,34 +313,35 @@ namespace connector { : public virtual Connector { public: - void operator()(Packet p); ///< Send out a packet + void operator()(Packet p); ///< Send out a packet + + void write(Packet p); ///< Alias for operator()(Packet p) - InputConnector & peer(); + InputConnector & peer() const; protected: OutputConnector(); }; - ///@{ - ///\addtogroup connectors - /** \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 discipline 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 SafeBool { public: PassiveInput(); - ActiveOutput & peer(); + ActiveOutput & peer() const; + + bool boolean_test() const; ///< \c true, if ! empty() template void qdisc(QDisc const & disc); ///< Change the queueing discipline @@ -310,20 +353,23 @@ namespace connector { private: void v_enqueueEvent(); void v_dequeueEvent(); + void v_unthrottleEvent(); boost::scoped_ptr qdisc_; - QueueingDiscipline::State qstate_; }; /** \brief Combination of PassiveConnector and OutputConnector */ class PassiveOutput - : public PassiveConnector, public OutputConnector + : public PassiveConnector, public OutputConnector, + public SafeBool { public: - ActiveInput & peer(); + ActiveInput & peer() const; - void connect(ActiveInput & target); + bool boolean_test() const; ///< Always \c true + + void connect(ActiveInput & target); ///< Internal: Use senf::ppi::connect() instead friend class ActiveInput; }; @@ -331,10 +377,13 @@ namespace connector { /** \brief Combination of ActiveConnector and InputConnector */ class ActiveInput - : public ActiveConnector, public InputConnector + : public ActiveConnector, public InputConnector, + public SafeBool { 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 @@ -345,15 +394,16 @@ namespace connector { /** \brief Combination of ActiveConnector and OutputConnector */ class ActiveOutput - : public ActiveConnector, public OutputConnector + : public ActiveConnector, public OutputConnector, + public SafeBool { public: - ActiveInput & peer(); + PassiveInput & peer() const; - void connect(PassiveInput & target); - }; + bool boolean_test() const; ///< \c true if peer() is ! throttled() - ///@} + void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead + }; }}}