/** \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 <deque>
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
#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////////////////////////////////////////
/** \namespace senf::ppi::connector
\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
private:
void onRequest() {
// 'input()' will return a senf::EthernetPacket packet handle
- try { output( input().find<IpPacket>() ); }
+ try { output( input().find<senf::IpPacket>() ); }
catch (senf::InvalidPacketChainException & ex) { ; }
}
};
\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
to the containing module)
*/
class Connector
- : boost::noncopyable
+ : ModuleManager::Initializable, boost::noncopyable
{
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
+
protected:
Connector();
virtual ~Connector();
void connect(Connector & target);
-
+
private:
+ virtual std::type_info const & packetTypeID();
+
void setModule(module::Module & module);
Connector * peer_;
Passive connectors always handle two throttling states:
- \li The \e native throttling state is set manually by the module. It is the throttling state
+ - 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.
void emit();
private:
+ virtual void v_init();
+
// 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
ActiveConnector();
private:
+ virtual void v_init();
+
// called by the peer() to forward throttling notifications
void notifyThrottle();
void notifyUnthrottle();
typedef std::vector<ForwardingRoute*> NotifyRoutes;
NotifyRoutes notifyRoutes_;
+ bool throttled_;
+
friend class senf::ppi::ForwardingRoute;
friend class PassiveConnector;
};
InputConnector();
private:
- void enqueue(Packet p);
+ void enqueue(Packet const & p);
virtual void v_requestEvent();
virtual void v_enqueueEvent();
: 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;
# define TypedConnector_Input read
# define TypedConnector_Output write
-# define TypedConnector(type, dir) \
+# define TypedConnector(pType, dir) \
template <class PacketType> \
- class type ## dir \
- : public Generic ## type ## dir, \
- private detail::Typed ## dir ## Mixin<type ## dir <PacketType>, PacketType> \
+ class pType ## dir \
+ : public Generic ## pType ## dir, \
+ private detail::Typed ## dir ## Mixin<pType ## dir <PacketType>, PacketType> \
{ \
- typedef detail::Typed ## dir ## Mixin<type ## dir <PacketType>, PacketType> mixin; \
+ typedef detail::Typed ## dir ## Mixin<pType ## dir <PacketType>, 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<pType ## dir <PacketType>, PacketType>; \
}; \
template <> \
- class type ## dir <Packet> : public Generic ## type ## dir \
+ class pType ## dir <Packet> : public Generic ## pType ## dir \
{}
TypedConnector( Passive, Input );
#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 <class PacketType>
+ template <class PacketType=Packet>
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()
/** \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
{
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()
/** \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 <class PacketType>
+ template <class PacketType=Packet>
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 <class PacketType>
+ template <class PacketType=Packet>
class PassiveOutput : public GenericPassiveOutput
{
public:
- PacketType operator()();
- PacketType write();
+ operator()(PacketType packet); ///< Send out a packet
+ void write(PacketType packet); ///< Alias for operator()
};
#endif