X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=PPI%2FConnectors.hh;h=e6b8c07af00c67d44e45ce232f4841876907d891;hb=d5a72d0b3f6fee56dba6de1c54cafb448ebe3457;hp=52663cc5b5289b8cc3cbaca6ac40da418bc6736c;hpb=69255c0f1669fc80b0e4a2bf524715f336b127ad;p=senf.git diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index 52663cc..e6b8c07 100644 --- a/PPI/Connectors.hh +++ b/PPI/Connectors.hh @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institute for Open Communication Systems (FOKUS) -// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Copyright (C) 2007 +// 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 @@ -23,18 +23,20 @@ /** \file \brief Connectors public header */ -#ifndef HH_Connectors_ -#define HH_Connectors_ 1 +#ifndef HH_SENF_PPI_Connectors_ +#define HH_SENF_PPI_Connectors_ 1 // Custom includes #include #include #include #include "../Utils/safe_bool.hh" +#include "../Utils/Exception.hh" #include "../Packets/Packets.hh" #include "predecl.hh" #include "detail/Callback.hh" #include "Queueing.hh" +#include "ModuleManager.hh" //#include "Connectors.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -44,23 +46,25 @@ namespace ppi { namespace connector { /** \namespace senf::ppi::connector - \brief Connector classes + \brief Connector classes - A connector has two independent properties + A connector has three independent properties \li it may be \e active or \e passive \li it may be an \e input or an \e output - + \li it has an (optional) packet type + \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. + signaled by the external framework. \e Input connectors receive packets, \e output + connectors send packets. All passive connectors call some onRequest callback whenever I/O needs to be performed. All - input modules possess a packet queue. + input connectors possess a packet queue. - We therefore have 4 connector types: + We therefore have 4 connector types each of which is parameterized by the type of packet + traversing the connector: \li senf::ppi::connector::ActiveInput - \li senf::ppi::connector::ActiveOutput - \li senf::ppi::connector::PassiveInput + \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 @@ -87,18 +91,67 @@ namespace connector { private: void onRequest() { // 'input()' will return a senf::EthernetPacket packet handle - try { output( input().find() ); } + try { output( input().find() ); } catch (senf::InvalidPacketChainException & ex) { ; } } }; \endcode - \see + + \section ppi_jacks Jacks + + A Jack is a packet type aware and possibly packet type converting reference to an arbitrary + connector of the same type. Jacks are used in groups to indirectly declare the input's and + output's + + \code + class MyGroup + { + private: + senf::ppi::module::PassiveQueue queue; + senf::ppi::module::RateAnalyzer analyzer; + + public: + senf::ppi::connector::ActiveInputJack input; + senf::ppi::connector::ActiveOutputJack output; + + MyGroup() + : queue (), analyzer (), input (queue.input), output (analyzer.output) + { + senf::ppi::connect(queue, analyzer); + } + }; + \endcode + + The jacks are initialized by passing an arbitrary compatible connector to the jack + constructor. A connector is compatible, if + \li It has the same input/output active/passive specification + \li Either the Jack or the Connector are generic (senf::Packet) or Jack and Connector have + the same packet type + + Jacks can be used wherever connectors may be used. Jacks may be defined anywhere, not only + in modules. It is however important to ensure that the lifetime of the jack does not exceed + the lifetime of the referenced connector. + + \see senf::ppi::module::Module \n senf::ppi::connect() \n \ref ppi_connectors */ + /** \brief Incompatible connectors connected + + This exception is thrown, when two incompatible connectors are connected. This happens if + both connectors of a senf::ppi::connect() statement declare a packet type (the connector + template argument) but they don't declare the same packet type. + + You need to ensure, that both connectors use the same packet type. + + \see senf::ppi::connect() + */ + struct IncompatibleConnectorsException : public senf::Exception + { IncompatibleConnectorsException() : senf::Exception("Incompatible connectors") {} }; + /** \brief Connector base-class This connector provides access to the generic connector facilities. This includes the @@ -106,24 +159,42 @@ namespace connector { to the containing module) */ class Connector - : boost::noncopyable + : ModuleManager::Initializable, boost::noncopyable { + SENF_LOG_CLASS_AREA(); + SENF_LOG_DEFAULT_LEVEL(senf::log::NOTICE); public: Connector & peer() const; ///< Get peer connected to this connector module::Module & module() const; ///< Get this connectors containing module + bool connected() const; ///< \c true, if connector connected, \c false otherwise + + void disconnect(); ///< Disconnect connector from peer + + enum TraceState { NO_TRACING, TRACE_IDS, TRACE_CONTENTS }; + + static void tracing(TraceState state); + static TraceState tracing(); + protected: Connector(); virtual ~Connector(); void connect(Connector & target); + void trace(Packet const & p, char const * label); + void throttleTrace(char const * label, char const * type); + private: + virtual std::type_info const & packetTypeID(); + void setModule(module::Module & module); Connector * peer_; module::Module * module_; + static TraceState traceState_; + friend class module::Module; }; @@ -134,16 +205,16 @@ namespace connector { 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 + Passive connectors always handle two throttling states: + + - 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 + - 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. */ - class PassiveConnector + class PassiveConnector : public virtual Connector { public: @@ -156,17 +227,17 @@ namespace connector { 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() const; ///< Get accumulative throttling state bool nativeThrottled() const; ///< Get native throttling state void throttle(); ///< Set native throttling void unthrottle(); ///< Revoke native throttling - + ActiveConnector & peer() const; protected: @@ -175,11 +246,13 @@ namespace connector { void emit(); private: - // Called by the routing to change the remote throttling state + virtual void v_init(); + + // Called by the routing to change the throttling state from forwarding routes void notifyThrottle(); ///< Forward a throttle notification to this connector void notifyUnthrottle(); ///< Forward an unthrottle notification to this connector - // Internal members to emit throttling notifications + // Internal members to emit throttling notifications to the connected peer void emitThrottle(); void emitUnthrottle(); @@ -211,7 +284,7 @@ namespace connector { notifications. These notifications should then either be processed by the module or be forwarded to other connectors. */ - class ActiveConnector + class ActiveConnector : public virtual Connector { typedef ppi::detail::Callback<>::type Callback; @@ -250,6 +323,8 @@ namespace connector { ActiveConnector(); private: + virtual void v_init(); + // called by the peer() to forward throttling notifications void notifyThrottle(); void notifyUnthrottle(); @@ -263,6 +338,8 @@ namespace connector { typedef std::vector NotifyRoutes; NotifyRoutes notifyRoutes_; + bool throttled_; + friend class senf::ppi::ForwardingRoute; friend class PassiveConnector; }; @@ -287,7 +364,7 @@ namespace connector { 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 + class InputConnector : public virtual Connector { typedef std::deque Queue; @@ -319,10 +396,10 @@ namespace connector { protected: InputConnector(); - + private: - void enqueue(Packet p); - + void enqueue(Packet const & p); + virtual void v_requestEvent(); virtual void v_enqueueEvent(); virtual void v_dequeueEvent(); @@ -331,27 +408,27 @@ namespace connector { friend class OutputConnector; }; - + /** \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 the queueing of the connected input. */ - class OutputConnector + class OutputConnector : public virtual Connector { public: - void operator()(Packet p); ///< Send out a packet + void operator()(Packet const & p); ///< Send out a packet - void write(Packet p); ///< Alias for operator()(Packet p) + void write(Packet const & p); ///< Alias for operator()(Packet p) InputConnector & peer() const; protected: OutputConnector(); }; - + /** \brief Combination of PassiveConnector and InputConnector The GenericPassiveInput automatically controls the connectors throttling state using a @@ -361,7 +438,7 @@ namespace connector { ThresholdQueueing(1,0) which will throttle the input whenever the queue is non-empty. */ - class GenericPassiveInput + class GenericPassiveInput : public PassiveConnector, public InputConnector, public safe_bool { @@ -374,7 +451,7 @@ namespace connector { 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 */ protected: @@ -450,19 +527,23 @@ namespace connector { # define TypedConnector_Input read # define TypedConnector_Output write -# define TypedConnector(type, dir) \ +# define TypedConnector(pType, dir) \ template \ - class type ## dir \ - : public Generic ## type ## dir, \ - private detail::Typed ## dir ## Mixin, PacketType> \ + class pType ## dir \ + : public Generic ## pType ## dir, \ + private detail::Typed ## dir ## Mixin, PacketType> \ { \ - typedef detail::Typed ## dir ## Mixin, PacketType> mixin; \ + typedef detail::Typed ## dir ## Mixin, PacketType> mixin; \ public: \ using mixin::operator(); \ using mixin::TypedConnector_ ## dir ; \ + private: \ + virtual std::type_info const & packetTypeID() \ + { return typeid(typename PacketType::type); } \ + friend class detail::Typed ## dir ## Mixin, PacketType>; \ }; \ template <> \ - class type ## dir : public Generic ## type ## dir \ + class pType ## dir : public Generic ## pType ## dir \ {} TypedConnector( Passive, Input ); @@ -477,20 +558,23 @@ namespace connector { #else /** \brief Connector actively reading packets + + \tparam PacketType Type of packet to read. Defaults to senf::Packet - 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. + 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 + senf::ppi::connector */ - template + template class ActiveInput : public GenericActiveInput { public: PacketType operator()(); ///< Read packet - /**< \throws std::bad_cast, if the connector receives a + /**< \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() @@ -498,9 +582,11 @@ namespace connector { /** \brief Connector passively receiving packets - 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 + \tparam PacketType Type of packet to read. Defaults to senf::Packet + + 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 @@ -511,7 +597,7 @@ namespace connector { { public: PacketType operator()(); ///< Read packet - /**< \throws std::bad_cast, if the connector receives a + /**< \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() @@ -519,36 +605,41 @@ namespace connector { /** \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. + \tparam PacketType Type of packet to send. Defaults to senf::Packet + + 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 + template class ActiveOutput : public GenericActiveOutput { public: - PacketType operator()(); - PacketType write(); + operator()(PacketType packet); ///< Send out a packet + void write(PacketType packet); ///< Alias for operator() }; /** \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. + \tparam PacketType Type of packet to send. Defaults to senf::Packet + + 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 + template class PassiveOutput : public GenericPassiveOutput { public: - PacketType operator()(); - PacketType write(); + operator()(PacketType packet); ///< Send out a packet + void write(PacketType packet); ///< Alias for operator() }; #endif