// Custom includes
#include "Route.hh"
+#include "Module.hh"
//#include "Connectors.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+// senf::ppi::connector::Connector
+
+prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
+{
+ SENF_ASSERT( module_ && ! peer_ && target.module_ && ! target.peer_ );
+ if (! (packetTypeID() == typeid(void) ||
+ target.packetTypeID() == typeid(void) ||
+ packetTypeID() == target.packetTypeID()) )
+ throw IncompatibleConnectorsException()
+ << ": " << prettyName(packetTypeID())
+ << " [in module " << prettyName(typeid(*module_)) << "] "
+ << ", " << prettyName(target.packetTypeID())
+ << " [in module " << prettyName(typeid(*target.module_)) << "]";
+
+ peer_ = & target;
+ target.peer_ = this;
+}
+
+///////////////////////////////////////////////////////////////////////////
// senf::ppi::connector::PassiveConnector
////////////////////////////////////////
\brief Connectors inline non-template implementation */
// Custom includes
+#include "../Utils/TypeInfo.hh"
#include "../Utils/senfassert.hh"
#define prefix_ inline
peer_->peer_ = 0;
}
-prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
-{
- SENF_ASSERT( ! peer_ && ! target.peer_ );
- peer_ = & target;
- target.peer_ = this;
-}
-
////////////////////////////////////////
// private members
#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"
\ref ppi_connectors
*/
+ 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() = 0;
+
void setModule(module::Module & module);
Connector * peer_;
# 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: \
- friend class detail::Typed ## dir ## Mixin<type ## dir <PacketType>, PacketType>; \
+ 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 \
+ { \
+ private: \
+ virtual std::type_info const & packetTypeID() { return typeid(void); } \
+ }
TypedConnector( Passive, Input );
TypedConnector( Passive, Output );
namespace {
- class TypedInputTest
+ template <class PacketType = senf::DataPacket>
+ class TypedPassiveInput
: public ppi::module::Module
{
- SENF_PPI_MODULE(TypedInputTest);
+ SENF_PPI_MODULE(TypedPassiveInput);
public:
- ppi::connector::PassiveInput<senf::DataPacket> input;
+ ppi::connector::PassiveInput<PacketType> input;
- TypedInputTest() {
+ TypedPassiveInput() {
noroute(input);
- input.onRequest(&TypedInputTest::request);
+ input.onRequest(&TypedPassiveInput::request);
}
void request() {
}
};
- class TypedOutputTest
+ template <class PacketType = senf::DataPacket>
+ class TypedActiveInput
: public ppi::module::Module
{
- SENF_PPI_MODULE(TypedOutputTest);
+ SENF_PPI_MODULE(TypedActiveInput);
public:
- ppi::connector::PassiveOutput<senf::DataPacket> output;
+ ppi::connector::ActiveInput<PacketType> input;
- TypedOutputTest() {
+ TypedActiveInput() {
+ noroute(input);
+ }
+ };
+
+ template <class PacketType = senf::DataPacket>
+ class TypedPassiveOutput
+ : public ppi::module::Module
+ {
+ SENF_PPI_MODULE(TypedPassiveOutput);
+
+ public:
+ ppi::connector::PassiveOutput<PacketType> output;
+
+ TypedPassiveOutput() {
noroute(output);
- output.onRequest(&TypedOutputTest::request);
+ output.onRequest(&TypedPassiveOutput::request);
}
void request() {
}
};
+ template <class PacketType = senf::DataPacket>
+ class TypedActiveOutput
+ : public ppi::module::Module
+ {
+ SENF_PPI_MODULE(TypedActiveOutput);
+
+ public:
+ ppi::connector::ActiveOutput<PacketType> output;
+
+ TypedActiveOutput() {
+ noroute(output);
+ }
+ };
+
+ struct MyPacketType : public senf::PacketTypeBase
+ {};
+
+ typedef senf::ConcretePacket<MyPacketType> MyPacket;
+
}
BOOST_AUTO_UNIT_TEST(typedInput)
{
debug::ActiveSource source;
- TypedInputTest target;
+ TypedPassiveInput<> target;
ppi::connect(source,target);
ppi::init();
BOOST_AUTO_UNIT_TEST(tyepdOutput)
{
- TypedOutputTest source;
+ TypedPassiveOutput<> source;
debug::ActiveSink target;
ppi::connect(source,target);
(void) target.request();
}
+BOOST_AUTO_UNIT_TEST(connectorTest)
+{
+ {
+ TypedPassiveInput<> input;
+ TypedActiveOutput<MyPacket> output;
+ BOOST_CHECK_THROW( ppi::connect(output, input),
+ ppi::connector::IncompatibleConnectorsException );
+ }
+ {
+ TypedPassiveInput<MyPacket> input;
+ TypedActiveOutput<> output;
+ BOOST_CHECK_THROW( ppi::connect(output, input),
+ ppi::connector::IncompatibleConnectorsException );
+ }
+ {
+ TypedPassiveInput<> input;
+ TypedActiveOutput<> output;
+ BOOST_CHECK_NO_THROW( ppi::connect(output, input) );
+ }
+ {
+ TypedPassiveInput<> input;
+ debug::ActiveSource output;
+ BOOST_CHECK_NO_THROW( ppi::connect(output, input) );
+ }
+ {
+ debug::ActiveSink input;
+ TypedPassiveOutput<> output;
+ BOOST_CHECK_NO_THROW( ppi::connect(output, input) );
+ }
+ {
+ debug::ActiveSink input;
+ debug::PassiveSource output;
+ BOOST_CHECK_NO_THROW( ppi::connect(output, input) );
+ }
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
class DgramReader
{
public:
+ typedef Packet PacketType;
typedef senf::ClientSocketHandle<
senf::MakeSocketPolicy< senf::ReadablePolicy,
senf::DatagramFramingPolicy >::policy > Handle;
public:
typedef typename Reader::Handle Handle; ///< Handle type requested by the reader
- connector::ActiveOutput<> output; ///< Output connector to which the data received is written
+ connector::ActiveOutput<typename Reader::PacketType> output;
+ ///< Output connector to which the data received is written
ActiveSocketSource(Handle handle); ///< Create new reader for the given handle
/**< Data will be read from \a handle and be parsed by \a
BOOST_CHECK( ! p->transport_error_indicator() );
BOOST_CHECK( p->pusi() );
BOOST_CHECK( ! p->transport_priority() );
- BOOST_CHECK_EQUAL( p->pid(), 0x010fu );
- BOOST_CHECK_EQUAL( p->transport_scrmbl_ctrl(), 0x0u );
+ BOOST_CHECK_EQUAL( p->pid(), 0x010fu );
+ BOOST_CHECK_EQUAL( p->transport_scrmbl_ctrl(), 0x0u );
BOOST_CHECK_EQUAL( p->adaptation_field_ctrl(), 0x1u );
- BOOST_CHECK_EQUAL( p->continuity_counter(), 0x0eu );
+ BOOST_CHECK_EQUAL( p->continuity_counter(), 0x0eu );
}
///////////////////////////////cc.e////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// senf::Exception
+
prefix_ senf::Exception::Exception(std::string const & description)
: message_(description)
{}
+prefix_ std::string const & senf::Exception::message()
+ const
+{
+ return message_;
+}
+
+prefix_ void senf::Exception::append(std::string text)
+{
+ message_ += text;
+}
+
///////////////////////////////////////////////////////////////////////////
+// senf::SystemException
prefix_ senf::SystemException::SystemException(std::string const & descr _SENF_EXC_DEBUG_ARGS_ND)
{
#define prefix_ inline
///////////////////////////////cti.p///////////////////////////////////////
-template <class Arg>
-prefix_ senf::Exception & senf::Exception::operator<<(Arg const & arg)
+template <class Exc, class Arg>
+prefix_ typename boost::enable_if< boost::is_convertible<Exc*,senf::Exception*>, Exc & >::type
+senf::operator<<(Exc const & exc, Arg const & arg)
{
- message_ += boost::lexical_cast<std::string>(arg);
- return *this;
+ const_cast<Exc &>(exc).append( boost::lexical_cast<std::string>(arg) );
+ return const_cast<Exc &>(exc);
}
/////////////////////////////cti.e///////////////////////////////////////
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/utility.hpp>
+#include <boost/type_traits/is_convertible.hpp>
//#include "Exception.mpp"
///////////////////////////////hh.p////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
virtual char const * what() const throw();
+ std::string const & message() const;
- template <class Arg>
- Exception & operator<<(Arg const & arg); ///< Extend exception description
- /**< Adds \a arg converted to string to the end of the
- exception description string. This operator allows to
- use Exception instances like streams. The conversion is
- performed using <code>boost::lexical_cast</code> and is
- therefor identical to a streaming operation.
- \see \ref exception */
+ void append(std::string text); ///< Extend exception description
+ /**< Adds \a text to the description text. */
protected:
Exception(std::string const & description = ""); ///< Initialize exception with string
std::string message_;
};
+ template <class Exc, class Arg>
+ typename boost::enable_if< boost::is_convertible<Exc*,Exception*>, Exc & >::type
+ operator<<(Exc const & exc, Arg const & arg); ///< Extend exception description
+ /**< Adds \a arg converted to string to the end of the
+ exception description string. This operator allows to
+ use Exception instances like streams. The conversion is
+ performed using <code>boost::lexical_cast</code> and is
+ therefor identical to a streaming operation.
+ \see \ref exception */
+
+
# ifdef SENF_DEBUG
# define _SENF_EXC_DEBUG_ARGS ,char const * file=0,int line=0
# define _SENF_EXC_DEBUG_ARGS_ND ,char const *file,int line
{
try {
try {
- throw senf::SystemException("::open()", ENOENT);
+ throw senf::SystemException("::open()", ENOENT) << "\nmore";
}
catch(senf::Exception & e) {
e << "\nx=" << 1 << boost::format("\ny=%d") % 2;
}
catch (senf::SystemException & e) {
BOOST_CHECK_EQUAL( e.errorNumber(), ENOENT );
- BOOST_CHECK_EQUAL( e.errorString(), "No such file or directory");
+ BOOST_CHECK_EQUAL( e.errorString(), "No such file or directory" );
+ BOOST_CHECK_EQUAL( e.what(), "[No such file or directory] ::open()\nmore\nx=1\ny=2" );
}
}