Console: Add console logging documentation
[senf.git] / PPI / Connectors.hh
index d96a0d7..2750224 100644 (file)
@@ -31,6 +31,7 @@
 #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"
@@ -46,9 +47,10 @@ namespace connector {
     /** \namespace senf::ppi::connector
         \brief Connector classes
 
-        A connector has two independent properties
-        - it may be \e active or \e passive
-        - it may be an \e input or an \e output
+        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
@@ -57,11 +59,12 @@ namespace connector {
         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::connector::ActiveInput
-        - senf::ppi::connector::ActiveOutput
-        - senf::ppi::connector::PassiveInput
-        - senf::ppi::connector::PassiveOutput.
+        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::PassiveOutput.
 
         Connectors are declared as module data members and are then externally connected to other
         modules.
@@ -99,6 +102,19 @@ namespace connector {
             \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
@@ -119,6 +135,8 @@ namespace connector {
         void connect(Connector & target);
 
     private:
+        virtual std::type_info const & packetTypeID();
+
         void setModule(module::Module & module);
 
         Connector * peer_;
@@ -450,19 +468,23 @@ namespace connector {
 
 #   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  );
@@ -477,20 +499,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::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()
@@ -498,9 +523,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 +538,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 +546,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 <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
 
-        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
+        write(PacketType packet);       ///< Alias for operator()
     };
 
 #endif