From: g0dil Date: Mon, 10 Mar 2008 23:16:29 +0000 (+0000) Subject: PPI: Add simple connector type compatibility check X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=17d44437f7fb8ee68a96ed55fc327c746c161142;p=senf.git PPI: Add simple connector type compatibility check Utils: BUGFIX: Fix use of operator<< together with throw git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@741 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/PPI/Connectors.cc b/PPI/Connectors.cc index ff29901..5c4ceff 100644 --- a/PPI/Connectors.cc +++ b/PPI/Connectors.cc @@ -28,12 +28,32 @@ // 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 //////////////////////////////////////// diff --git a/PPI/Connectors.cci b/PPI/Connectors.cci index e4647d7..c61555c 100644 --- a/PPI/Connectors.cci +++ b/PPI/Connectors.cci @@ -24,6 +24,7 @@ \brief Connectors inline non-template implementation */ // Custom includes +#include "../Utils/TypeInfo.hh" #include "../Utils/senfassert.hh" #define prefix_ inline @@ -59,13 +60,6 @@ prefix_ senf::ppi::connector::Connector::~Connector() peer_->peer_ = 0; } -prefix_ void senf::ppi::connector::Connector::connect(Connector & target) -{ - SENF_ASSERT( ! peer_ && ! target.peer_ ); - peer_ = & target; - target.peer_ = this; -} - //////////////////////////////////////// // private members diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index a69c3d8..be55849 100644 --- a/PPI/Connectors.hh +++ b/PPI/Connectors.hh @@ -31,6 +31,7 @@ #include #include #include "../Utils/safe_bool.hh" +#include "../Utils/Exception.hh" #include "../Packets/Packets.hh" #include "predecl.hh" #include "detail/Callback.hh" @@ -99,6 +100,9 @@ namespace connector { \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 @@ -119,6 +123,8 @@ namespace connector { void connect(Connector & target); private: + virtual std::type_info const & packetTypeID() = 0; + void setModule(module::Module & module); Connector * peer_; @@ -450,22 +456,27 @@ 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: \ - friend class detail::Typed ## dir ## Mixin, PacketType>; \ + 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 \ + { \ + private: \ + virtual std::type_info const & packetTypeID() { return typeid(void); } \ + } TypedConnector( Passive, Input ); TypedConnector( Passive, Output ); diff --git a/PPI/Connectors.test.cc b/PPI/Connectors.test.cc index 639f58b..6b95fc2 100644 --- a/PPI/Connectors.test.cc +++ b/PPI/Connectors.test.cc @@ -286,17 +286,18 @@ BOOST_AUTO_UNIT_TEST(activeOutput) namespace { - class TypedInputTest + template + class TypedPassiveInput : public ppi::module::Module { - SENF_PPI_MODULE(TypedInputTest); + SENF_PPI_MODULE(TypedPassiveInput); public: - ppi::connector::PassiveInput input; + ppi::connector::PassiveInput input; - TypedInputTest() { + TypedPassiveInput() { noroute(input); - input.onRequest(&TypedInputTest::request); + input.onRequest(&TypedPassiveInput::request); } void request() { @@ -305,17 +306,32 @@ namespace { } }; - class TypedOutputTest + template + class TypedActiveInput : public ppi::module::Module { - SENF_PPI_MODULE(TypedOutputTest); + SENF_PPI_MODULE(TypedActiveInput); public: - ppi::connector::PassiveOutput output; + ppi::connector::ActiveInput input; - TypedOutputTest() { + TypedActiveInput() { + noroute(input); + } + }; + + template + class TypedPassiveOutput + : public ppi::module::Module + { + SENF_PPI_MODULE(TypedPassiveOutput); + + public: + ppi::connector::PassiveOutput output; + + TypedPassiveOutput() { noroute(output); - output.onRequest(&TypedOutputTest::request); + output.onRequest(&TypedPassiveOutput::request); } void request() { @@ -325,12 +341,31 @@ namespace { } }; + template + class TypedActiveOutput + : public ppi::module::Module + { + SENF_PPI_MODULE(TypedActiveOutput); + + public: + ppi::connector::ActiveOutput output; + + TypedActiveOutput() { + noroute(output); + } + }; + + struct MyPacketType : public senf::PacketTypeBase + {}; + + typedef senf::ConcretePacket MyPacket; + } BOOST_AUTO_UNIT_TEST(typedInput) { debug::ActiveSource source; - TypedInputTest target; + TypedPassiveInput<> target; ppi::connect(source,target); ppi::init(); @@ -341,7 +376,7 @@ BOOST_AUTO_UNIT_TEST(typedInput) BOOST_AUTO_UNIT_TEST(tyepdOutput) { - TypedOutputTest source; + TypedPassiveOutput<> source; debug::ActiveSink target; ppi::connect(source,target); @@ -350,6 +385,42 @@ BOOST_AUTO_UNIT_TEST(tyepdOutput) (void) target.request(); } +BOOST_AUTO_UNIT_TEST(connectorTest) +{ + { + TypedPassiveInput<> input; + TypedActiveOutput output; + BOOST_CHECK_THROW( ppi::connect(output, input), + ppi::connector::IncompatibleConnectorsException ); + } + { + TypedPassiveInput 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_ diff --git a/PPI/SocketSource.hh b/PPI/SocketSource.hh index 477df4b..a74fdbc 100644 --- a/PPI/SocketSource.hh +++ b/PPI/SocketSource.hh @@ -53,6 +53,7 @@ namespace ppi { class DgramReader { public: + typedef Packet PacketType; typedef senf::ClientSocketHandle< senf::MakeSocketPolicy< senf::ReadablePolicy, senf::DatagramFramingPolicy >::policy > Handle; @@ -111,7 +112,8 @@ namespace module { 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 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 diff --git a/Packets/MPEGDVBBundle/TransportPacket.test.cc b/Packets/MPEGDVBBundle/TransportPacket.test.cc index 91f0f28..0fee6b2 100644 --- a/Packets/MPEGDVBBundle/TransportPacket.test.cc +++ b/Packets/MPEGDVBBundle/TransportPacket.test.cc @@ -73,10 +73,10 @@ BOOST_AUTO_UNIT_TEST(transportPacket_packet) 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//////////////////////////////////////// diff --git a/Utils/Exception.cci b/Utils/Exception.cci index e7a9c53..b745f80 100644 --- a/Utils/Exception.cci +++ b/Utils/Exception.cci @@ -29,11 +29,24 @@ /////////////////////////////////////////////////////////////////////////// // 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) { diff --git a/Utils/Exception.cti b/Utils/Exception.cti index 3588cdc..a398908 100644 --- a/Utils/Exception.cti +++ b/Utils/Exception.cti @@ -31,11 +31,12 @@ #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// -template -prefix_ senf::Exception & senf::Exception::operator<<(Arg const & arg) +template +prefix_ typename boost::enable_if< boost::is_convertible, Exc & >::type +senf::operator<<(Exc const & exc, Arg const & arg) { - message_ += boost::lexical_cast(arg); - return *this; + const_cast(exc).append( boost::lexical_cast(arg) ); + return const_cast(exc); } /////////////////////////////cti.e/////////////////////////////////////// diff --git a/Utils/Exception.hh b/Utils/Exception.hh index eda57d1..5f00926 100644 --- a/Utils/Exception.hh +++ b/Utils/Exception.hh @@ -34,6 +34,7 @@ #include #include #include +#include //#include "Exception.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -103,15 +104,10 @@ namespace senf { /////////////////////////////////////////////////////////////////////////// virtual char const * what() const throw(); + std::string const & message() const; - template - 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 boost::lexical_cast 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 @@ -124,6 +120,17 @@ namespace senf { std::string message_; }; + template + typename boost::enable_if< boost::is_convertible, 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 boost::lexical_cast 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 diff --git a/Utils/Exception.test.cc b/Utils/Exception.test.cc index 3e51428..d390062 100644 --- a/Utils/Exception.test.cc +++ b/Utils/Exception.test.cc @@ -41,7 +41,7 @@ BOOST_AUTO_UNIT_TEST(errnoException) { 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; @@ -50,7 +50,8 @@ BOOST_AUTO_UNIT_TEST(errnoException) } 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" ); } }