#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"
/** \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
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:
+ 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
\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
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.
# 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.
\see GenericActiveInput \n
- senf::ppi::connectro
+ senf::ppi::connector
*/
- template <class PacketType>
+ template <class PacketType=Packet>
class ActiveInput : public GenericActiveInput
{
public:
/** \brief Connector passively receiving packets
+ \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
/** \brief Connector actively sending packets
+ \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
+ write(PacketType packet); ///< Alias for operator()
};
/** \brief Connector passively providing packets
+ \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
+ write(PacketType packet); ///< Alias for operator()
};
#endif