X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=PPI%2FConnectors.hh;h=52663cc5b5289b8cc3cbaca6ac40da418bc6736c;hb=e7ac3fef18af5ec0076f02290ad439a9d6e05491;hp=6e01ca36cfdbb1b6d78b247f4376f6186142c33b;hpb=f539f4271d470794a773a92bacd8ba086c9bc1cd;p=senf.git diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index 6e01ca3..52663cc 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 @@ -21,22 +23,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 +30,8 @@ #include #include #include -#include "Utils/SafeBool.hh" -#include "Packets/Packets.hh" +#include "../Utils/safe_bool.hh" +#include "../Packets/Packets.hh" #include "predecl.hh" #include "detail/Callback.hh" #include "Queueing.hh" @@ -57,7 +43,63 @@ 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. + + The connectors each take an optional template argument. If this argument is specified, it + must be the type of packet expected or sent on this connector. If it is not specified, + packets will be passed using the generic Packet handle. + + \code + class IpFilter : public senf::ppi::module::Module + { + SENF_PPI_MODULE(SomeModule); + + public: + senf::ppi::connector::ActiveInput input; + senf::ppi::connector::PassiveOutput output; + + IpFilter() { + route(input, output); + input.onRequest(&IpFilter::onRequest); + } + + private: + void onRequest() { + // 'input()' will return a senf::EthernetPacket packet handle + try { output( input().find() ); } + catch (senf::InvalidPacketChainException & ex) { ; } + } + }; + \endcode + + \see + senf::ppi::module::Module \n + senf::ppi::connect() \n + \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 @@ -85,7 +127,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 +176,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(); @@ -144,17 +186,22 @@ namespace connector { // Called after unthrottling the connector virtual void v_unthrottleEvent(); - typedef detail::Callback<>::type Callback; + // called by ForwardingRoute to register a new route + void registerRoute(ForwardingRoute & route); + + typedef ppi::detail::Callback<>::type Callback; Callback callback_; bool remoteThrottled_; bool nativeThrottled_; - friend class senf::ppi::detail::ForwardForwardingRouteImplementation; - friend class senf::ppi::detail::BackwardForwardingRouteImplementation; + 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 @@ -167,7 +214,7 @@ namespace connector { class ActiveConnector : public virtual Connector { - typedef detail::Callback<>::type Callback; + typedef ppi::detail::Callback<>::type Callback; public: template void onThrottle(Handler handler); ///< Register throttle notification handler @@ -180,7 +227,7 @@ namespace connector { \param[in] handler Handler to call on throttle notifications. */ - void onThrottle(); + void onThrottle(); ///< Clear throttle notification handler template void onUnthrottle(Handler handler); ///< Register unthrottle notification handler @@ -191,9 +238,11 @@ 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(); + void onUnthrottle(); ///< Clear unthrottle notification handler + + bool throttled() const; ///< \c true, if peer() is throttled PassiveConnector & peer() const; @@ -218,7 +267,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 @@ -235,7 +284,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 @@ -246,6 +295,7 @@ namespace connector { 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 @@ -256,6 +306,8 @@ namespace connector { logic error in the module implementation and an exception is raised. */ + Packet read(); ///< Alias for operator()() + OutputConnector & peer() const; queue_iterator begin() const; ///< Access queue begin (head) @@ -280,7 +332,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 @@ -290,7 +342,9 @@ 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() const; @@ -298,28 +352,23 @@ namespace connector { OutputConnector(); }; - ///@{ - ///\addtogroup connectors - /** \brief Combination of PassiveConnector and InputConnector - 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 + The GenericPassiveInput 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 + class GenericPassiveInput : public PassiveConnector, public InputConnector, - public SafeBool + public safe_bool { public: - PassiveInput(); - - ActiveOutput & peer() const; + GenericActiveOutput & peer() const; - bool boolean_test() const; + bool boolean_test() const; ///< \c true, if ! empty() template void qdisc(QDisc const & disc); ///< Change the queueing discipline @@ -328,6 +377,9 @@ namespace connector { \param[in] disc New queueing discipline */ + protected: + GenericPassiveInput(); + private: void v_enqueueEvent(); void v_dequeueEvent(); @@ -338,52 +390,168 @@ namespace connector { /** \brief Combination of PassiveConnector and OutputConnector */ - class PassiveOutput + class GenericPassiveOutput : public PassiveConnector, public OutputConnector, - public SafeBool + public safe_bool { public: - ActiveInput & peer() const; + GenericActiveInput & peer() const; + + bool boolean_test() const; ///< Always \c true - bool boolean_test() const; + void connect(GenericActiveInput & target); ///< Internal: Use senf::ppi::connect() instead - void connect(ActiveInput & target); + friend class GenericActiveInput; + + protected: + GenericPassiveOutput(); - friend class ActiveInput; }; /** \brief Combination of ActiveConnector and InputConnector */ - class ActiveInput + class GenericActiveInput : public ActiveConnector, public InputConnector, - public SafeBool + public safe_bool { public: - PassiveOutput & peer() const; + GenericPassiveOutput & peer() const; - bool boolean_test() const; + bool boolean_test() const; ///< \c true, if ! empty() or ! throttled() void request(); ///< request more packets without dequeuing any packet + protected: + GenericActiveInput(); + private: void v_requestEvent(); }; /** \brief Combination of ActiveConnector and OutputConnector */ - class ActiveOutput + class GenericActiveOutput : public ActiveConnector, public OutputConnector, - public SafeBool + public safe_bool + { + public: + GenericPassiveInput & peer() const; + + bool boolean_test() const; ///< \c true if peer() is ! throttled() + + void connect(GenericPassiveInput & target); ///< Internal: Use senf::ppi::connect() instead + + protected: + GenericActiveOutput(); + + }; + +#ifndef DOXYGEN + +# define TypedConnector_Input read +# define TypedConnector_Output write +# define TypedConnector(type, dir) \ + template \ + class type ## dir \ + : public Generic ## type ## dir, \ + private detail::Typed ## dir ## Mixin, PacketType> \ + { \ + typedef detail::Typed ## dir ## Mixin, PacketType> mixin; \ + public: \ + using mixin::operator(); \ + using mixin::TypedConnector_ ## dir ; \ + }; \ + template <> \ + class type ## dir : public Generic ## type ## dir \ + {} + + TypedConnector( Passive, Input ); + TypedConnector( Passive, Output ); + TypedConnector( Active, Input ); + TypedConnector( Active, Output ); + +# undef TypedConnector +# undef TypedConnector_Input +# undef TypedConnector_Output + +#else + + /** \brief Connector actively reading packets + + The ActiveInput connector template reads data actively from a connected module. This class + is completely implemented via it's base-class, GenericActiveInput, the only difference is + that read packets are returned as \a PacketType instead of generic senf::Packet references. + + \see GenericActiveInput \n + senf::ppi::connectro + */ + template + class ActiveInput : public GenericActiveInput { public: - PassiveInput & peer() const; + PacketType operator()(); ///< Read packet + /**< \throws std::bad_cast, if the connector receives a + Packet which is not of type \a PacketType. + \returns newly read packet reference. */ + PacketType read(); ///< Alias for operator() + }; - bool boolean_test() const; + /** \brief Connector passively receiving packets - void connect(PassiveInput & target); + The PassiveInput connector template receives packets sent to it from a connected + module. This class is completely implemented via it's base-class, GenericPassiveInput, the + only difference is that read packets are returned as \a PacketType instead of generic + senf::Packet references. + + \see GenericPassiveInput \n + senf::ppi::connector + */ + template + class PassiveInput : public GenericPassiveInput + { + public: + PacketType operator()(); ///< Read packet + /**< \throws std::bad_cast, if the connector receives a + Packet which is not of type \a PacketType. + \returns newly read packet reference. */ + PacketType read(); ///< Alias for operator() }; - ///@} + /** \brief Connector actively sending packets + + The ActiveOutput connector template sends data actively to a connected module. This class is + completely implemented via it's base-class, GenericActiveOutput, the only difference is that + it only sends packets of type \a PacketType. + + \see GenericActiveOutput \n + senf::ppi::connector + */ + template + class ActiveOutput : public GenericActiveOutput + { + public: + PacketType operator()(); + PacketType write(); + }; + + /** \brief Connector passively providing packets + + The PassiveOutput connector template provides data passively to a connected module whenever + signaled. This class is completely implemented via it's base-class, GenericPassiveOutput, the + only difference is that it only sends packets of type \a PacketType. + + \see GenericPassiveOutput \n + senf::ppi::connector + */ + template + class PassiveOutput : public GenericPassiveOutput + { + public: + PacketType operator()(); + PacketType write(); + }; + +#endif }}}