From: g0dil Date: Mon, 11 Jun 2007 23:29:13 +0000 (+0000) Subject: Several FIXME items: X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=8421c3a8da7485cb8781045494ecaab3ed84f403;p=senf.git Several FIXME items: * Allow empty FileHandle/SocketHandle etc instances * Make ServerSocketHandle::listen depend on AddressingPolicy * Replace all occurences of inet_ntoa with inet_ntop (thread safety) * Fix handling of exceptions in ReadHelper/WriteHelper * Fix Scheduler ERR/HUP semantics git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@256 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/DefaultBundle/IpV4Packet.cc b/Packets/DefaultBundle/IpV4Packet.cc index 8f7c064..6b163a6 100644 --- a/Packets/DefaultBundle/IpV4Packet.cc +++ b/Packets/DefaultBundle/IpV4Packet.cc @@ -56,9 +56,10 @@ prefix_ void senf::IpV4Packet::v_dump(std::ostream & os) { struct in_addr in; in.s_addr = htonl(source()); - std::string src (inet_ntoa(in)); + char buffer[128]; + std::string src (inet_ntop(AF_INET,&in,buffer,128)); in.s_addr = htonl(destination()); - std::string dst (inet_ntoa(in)); + std::string dst (inet_ntop(AF_INET,&in,buffer,128)); os << "Internet protocol Version 4:\n" << " version : " << version() << "\n" << " IHL : " << ihl() << "\n" diff --git a/Packets/Packet.cci b/Packets/Packet.cci index d9dcfc0..72f7943 100644 --- a/Packets/Packet.cci +++ b/Packets/Packet.cci @@ -154,9 +154,8 @@ prefix_ senf::Packet::ptr senf::Packet::head() prefix_ senf::Packet::~Packet() { - /** \fixme This is bad ... we cannot check this since this - assertion fails at the moment if the Packet constructor throws - ... hrmpf ... we really need to initialize refcount_ to 0 and + /** \todo This is sad ... we cannot check this since this assertion fails at the moment if the + Packet constructor throws ... hrmpf ... we really should initialize refcount_ to 0 and remove the 'false' argument to the ptr constructor in create */ // BOOST_ASSERT( !this->refcount_ && !this->impl_ ); SATCOM_PKF_REFC_MSG("] Packet::~Packet (" << this << ")\n"); diff --git a/Packets/ParseListS.ct b/Packets/ParseListS.ct index ba89360..1c01036 100644 --- a/Packets/ParseListS.ct +++ b/Packets/ParseListS.ct @@ -80,9 +80,8 @@ template template prefix_ void senf::Parse_ListS_wrapper::insert(iterator pos, - Value const & t) + Value const & t) { - /** \fixme What, if pos == end() / default constructed iterator ? */ size_type ix (pos.raw()-container_.begin()); container_.insert(pos.raw(),t.bytes(),0); Parser(container_.begin()+ix).value(t); @@ -92,7 +91,7 @@ template template prefix_ void senf::Parse_ListS_wrapper::insert(iterator pos, size_type n, - Value const & t) + Value const & t) { size_type ix (pos.raw()-container_.begin()); container_.insert(pos.raw(),n*t.bytes(),0); @@ -105,8 +104,8 @@ template template prefix_ void senf::Parse_ListS_wrapper::insert(iterator pos, - InputIterator f, - InputIterator l) + InputIterator f, + InputIterator l) { /** \todo Optimize this for random-access and multi-pass iterators */ for (;f!=l;++f,++pos) insert(pos,*f); diff --git a/Scheduler/ReadHelper.ct b/Scheduler/ReadHelper.ct index 3ac3df5..40ac199 100644 --- a/Scheduler/ReadHelper.ct +++ b/Scheduler/ReadHelper.ct @@ -69,7 +69,6 @@ template prefix_ void senf::ReadHelper::process(Handle handle, senf::Scheduler::EventId event) { - /** \fixme Move the done() calls to outside the try/catch block */ try { if (event != senf::Scheduler::EV_READ) throw SystemException(EPIPE); @@ -82,13 +81,15 @@ prefix_ void senf::ReadHelper::process(Handle handle, tail_.assign(data_,n,std::string::npos); data_.erase(n); } - done(); } } catch (senf::SystemException const & ex) { errno_ = ex.err; done(); + return; } + if (complete_) + done(); } template diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index f692402..e4bc1a0 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -116,8 +116,6 @@ prefix_ void senf::Scheduler::do_add(int fd, SimpleCallback const & cb, int even if (eventMask & EV_READ) i->second.cb_read = cb; if (eventMask & EV_PRIO) i->second.cb_prio = cb; if (eventMask & EV_WRITE) i->second.cb_write = cb; - if (eventMask & EV_HUP) i->second.cb_hup = cb; - if (eventMask & EV_ERR) i->second.cb_err = cb; epoll_event ev; memset(&ev,0,sizeof(ev)); @@ -137,8 +135,6 @@ prefix_ void senf::Scheduler::do_remove(int fd, int eventMask) if (eventMask & EV_READ) i->second.cb_read = 0; if (eventMask & EV_PRIO) i->second.cb_prio = 0; if (eventMask & EV_WRITE) i->second.cb_write = 0; - if (eventMask & EV_HUP) i->second.cb_hup = 0; - if (eventMask & EV_ERR) i->second.cb_err = 0; epoll_event ev; memset(&ev,0,sizeof(ev)); @@ -163,8 +159,6 @@ prefix_ int senf::Scheduler::EventSpec::epollMask() if (cb_read) mask |= EPOLLIN; if (cb_prio) mask |= EPOLLPRI; if (cb_write) mask |= EPOLLOUT; - if (cb_hup) mask |= EPOLLHUP; - if (cb_err) mask |= EPOLLERR; return mask; } @@ -185,50 +179,46 @@ prefix_ void senf::Scheduler::process() struct epoll_event ev; int events = epoll_wait(epollFd_, &ev, 1, timeout); if (events<0) - // Hmm ... man epoll says, it will NOT return with EINTR ?? + // Hmm ... man epoll says, it will NOT return with EINTR. I hope, this is true :-) throw SystemException(errno); if (events==0) - // Timeout .. it will be run when reachiung the top of the loop + // Timeout .. the handler will be run when going back to the loop top continue; FdTable::iterator i = fdTable_.find(ev.data.fd); BOOST_ASSERT (i != fdTable_.end() ); - EventSpec const & spec (i->second); + // \todo Make this more efficient. Instead of copying the event-spec it should be + // revalidated by monitoring add/remove calls + EventSpec spec (i->second); + + unsigned extraFlags (0); + if (ev.events & EPOLLHUP) extraFlags |= EV_HUP; + if (ev.events & EPOLLERR) extraFlags |= EV_ERR; if (ev.events & EPOLLIN) { BOOST_ASSERT(spec.cb_read); - spec.cb_read(EV_READ); + spec.cb_read(EventId(EV_READ | extraFlags)); } else if (ev.events & EPOLLPRI) { BOOST_ASSERT(spec.cb_prio); - spec.cb_prio(EV_PRIO); + spec.cb_prio(EventId(EV_PRIO | extraFlags)); } else if (ev.events & EPOLLOUT) { BOOST_ASSERT(spec.cb_write); - spec.cb_write(EV_WRITE); - } - - else if (ev.events & EPOLLHUP) { - if (spec.cb_hup) - spec.cb_hup(EV_HUP); - else if (ev.events & EPOLLERR) { - /** \fixme This is stupid, if cb_write and cb_read are - the same. The same below. We really have to - exactly define sane semantics of what to do on - EPOLLHUP and EPOLLERR. */ - if (spec.cb_write) spec.cb_write(EV_HUP); - if (spec.cb_read) spec.cb_read(EV_HUP); - } + spec.cb_write(EventId(EV_WRITE | extraFlags)); } - else if (ev.events & EPOLLERR && ! ev.events & EPOLLHUP) { - if (spec.cb_err) - spec.cb_err(EV_ERR); - else { - if (spec.cb_write) spec.cb_write(EV_ERR); - if (spec.cb_read) spec.cb_read(EV_ERR); - } + else { + // This branch is only taken, if HUP or ERR is signaled but none of IN/OUT/PRI. + // In this case we will signal all registered callbacks. The callbacks must be + // prepared to be called multiple times if they are registered to more than + // one event. + if (spec.cb_write) + spec.cb_write(EventId(extraFlags)); + if (spec.cb_prio) + spec.cb_prio(EventId(extraFlags)); + if (spec.cb_read) + spec.cb_read(EventId(extraFlags)); } - } } diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 1887f5d..8fe4f15 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -76,8 +76,9 @@ namespace senf { /// \brief Types of file descriptor events */ enum EventId { EV_NONE=0, - EV_READ=1, EV_PRIO=2, EV_WRITE=4, EV_HUP=8, EV_ERR=16, - EV_ALL=31 }; + EV_READ=1, EV_PRIO=2, EV_WRITE=4, + EV_ALL=7, + EV_HUP=8, EV_ERR=16 }; /** \brief Template typedef for Callback type @@ -180,8 +181,6 @@ namespace senf { SimpleCallback cb_read; SimpleCallback cb_prio; SimpleCallback cb_write; - SimpleCallback cb_hup; - SimpleCallback cb_err; int epollMask() const; }; diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index 78aaa4d..104268b 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -143,7 +143,7 @@ namespace { void callback(int fd, Scheduler::EventId ev) { event = ev; - switch (event) { + switch (event & Scheduler::EV_ALL) { case Scheduler::EV_READ: size = recv(fd,buffer,1024,0); break; @@ -155,11 +155,6 @@ namespace { size = write(fd,buffer,size); Scheduler::instance().terminate(); break; - case Scheduler::EV_HUP: - case Scheduler::EV_ERR: - case Scheduler::EV_NONE: - case Scheduler::EV_ALL: - ; } Scheduler::instance().terminate(); } @@ -246,7 +241,7 @@ BOOST_AUTO_UNIT_TEST(scheduler) BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle,Scheduler::EV_WRITE) ); event = Scheduler::EV_NONE; BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); - BOOST_CHECK_EQUAL( event, Scheduler::EV_READ ); + BOOST_CHECK_EQUAL( event, Scheduler::EventId(Scheduler::EV_READ|Scheduler::EV_HUP) ); BOOST_REQUIRE_EQUAL( size, 2 ); buffer[size]=0; BOOST_CHECK_EQUAL( buffer, "OK" ); diff --git a/Scheduler/WriteHelper.ct b/Scheduler/WriteHelper.ct index 2fa2602..9dfa747 100644 --- a/Scheduler/WriteHelper.ct +++ b/Scheduler/WriteHelper.ct @@ -75,20 +75,23 @@ template prefix_ void senf::WriteHelper::process(Handle handle, senf::Scheduler::EventId event) { - /** \fixme Move the done() calls to outside the try/catch block */ + bool complete_ (false); try { if (event != senf::Scheduler::EV_WRITE) throw senf::SystemException(EPIPE); offset_ += handle.write(data_.data()+offset_,data_.size()-offset_); if (offset_ >= data_.size()) { data_.erase(); - done(); + complete_ = true; } } catch (senf::SystemException const & ex) { errno_ = ex.err; done(); + return; } + if (complete_) + done(); } template diff --git a/Socket/ClientSocketHandle.cti b/Socket/ClientSocketHandle.cti index 8591399..d836823 100644 --- a/Socket/ClientSocketHandle.cti +++ b/Socket/ClientSocketHandle.cti @@ -99,6 +99,10 @@ writeto(Handle & handle, ForwardReadableRange & range, typename Handle::Address // structors template +prefix_ senf::ClientSocketHandle::ClientSocketHandle() +{} + +template template prefix_ senf::ClientSocketHandle:: ClientSocketHandle(ClientSocketHandle other, diff --git a/Socket/ClientSocketHandle.hh b/Socket/ClientSocketHandle.hh index 368e3cd..38e7ea0 100644 --- a/Socket/ClientSocketHandle.hh +++ b/Socket/ClientSocketHandle.hh @@ -79,13 +79,6 @@ namespace senf { typelist of Poclicy classes which can be accessed. You use protocol() to access a protocol class. \c Policies can of course be underspecified or even empty. - \idea add more flexible read/write members for a) boost::arrays and arrays of other types b) - std::vector (which uses contiguous memory ..) c) other random-access containers (we should - use some configurable trait class to identify containers with contiguous storage). Probably - we should just use a generic Boost.Range interface. Here we again come to the point: make - all except the most basic members be non-member algorithms ? this would make the - configuration of such extenden members more flexible. - \see \ref policy_group \n \ref protocol_group */ @@ -116,11 +109,14 @@ namespace senf { ///\name Structors and default members ///@{ - // no default constructor + // default default constructor // default copy constructor // default copy assignment // default destructor + // here to implement + ClientSocketHandle(); + // conversion constructors template ClientSocketHandle(ClientSocketHandle other, @@ -181,14 +177,15 @@ namespace senf { \param[in/out] range Range to store data in \returns past-the-end iterator pointer to after the last read character - \see \ref read() */ + \see \ref read() \n + Boost.Range */ template typename boost::range_iterator::type read (ForwardWritableRange & range); ///< Read data into range - /**< \see - read(ForwardWritableRange const &) \n - read() */ + /**< \see read(ForwardWritableRange const &) \n + read() \n + Boost.Range */ template void read (Sequence & container, unsigned limit); ///< Read data into container @@ -243,14 +240,15 @@ namespace senf { received \returns past-the-end iterator pointer to after the last read character - \see \ref readfrom() */ + \see \ref readfrom() \n + Boost.Range */ template typename boost::range_iterator::type readfrom (ForwardWritableRange & range, Address & from); ///< Read data into range - /**< \see - readfrom(ForwardWritableRange const&,Address&) \n - readfrom() */ + /**< \see readfrom(ForwardWritableRange const&,Address&) \n + readfrom() \n + Boost.Range */ template void readfrom (Sequence & container, Address & from, unsigned limit); ///< Read data into container @@ -303,7 +301,8 @@ namespace senf { /**< \param[in] start beginning of area to write \param[in] end past-the-end pointer to area to write \returns past-the-end pointer after last byte written - \see \ref write() */ + \see \ref write() \n + Boost.Range */ /** \brief Write data to unconnected socket @@ -332,7 +331,8 @@ namespace senf { \param[in] start address of buffer to write \param[in] end past-the-end pointer after data to write \returns past-the-end iterator after last byte written - \see \ref writeto() */ + \see \ref writeto() \n + Boost.Range */ /////////////////////////////////////////////////////////////////////////// ///\name Addressing diff --git a/Socket/CommunicationPolicy.cc b/Socket/CommunicationPolicy.cc index b7ddb9f..eedc8fb 100644 --- a/Socket/CommunicationPolicy.cc +++ b/Socket/CommunicationPolicy.cc @@ -38,8 +38,8 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -prefix_ void senf::ConnectedCommunicationPolicy::listen(FileHandle handle, - unsigned backlog) +prefix_ void senf::ConnectedCommunicationPolicy::do_listen(FileHandle handle, + unsigned backlog) { ::listen(handle.fd(),backlog); } diff --git a/Socket/CommunicationPolicy.cti b/Socket/CommunicationPolicy.cti index b801ae1..233dc3b 100644 --- a/Socket/CommunicationPolicy.cti +++ b/Socket/CommunicationPolicy.cti @@ -32,6 +32,14 @@ ///////////////////////////////cti.p/////////////////////////////////////// template +prefix_ void senf::ConnectedCommunicationPolicy:: +listen(ServerSocketHandle handle, unsigned backlog, + typename IfAddressingPolicyIsNot::type *) +{ + do_listen(handle, backlog); +} + +template prefix_ int senf::ConnectedCommunicationPolicy:: accept(ServerSocketHandle handle, typename ServerSocketHandle::Address & address, diff --git a/Socket/CommunicationPolicy.hh b/Socket/CommunicationPolicy.hh index fe89926..9c0af83 100644 --- a/Socket/CommunicationPolicy.hh +++ b/Socket/CommunicationPolicy.hh @@ -51,14 +51,12 @@ namespace senf { */ struct ConnectedCommunicationPolicy : public CommunicationPolicyBase { - static void listen(FileHandle handle, unsigned backlog); + template + static void listen(ServerSocketHandle handle, unsigned backlog, + typename IfAddressingPolicyIsNot::type * = 0); ///< Enable establishing new connections on the socket /**< \param[in] handle socket handle to enable reception on - \param[in] backlog size of backlog queue - - \fixme listen probably makes no sense without accept, - so listen() should depend on AddressingPolicy - too. */ + \param[in] backlog size of backlog queue */ template static int accept(ServerSocketHandle handle, typename ServerSocketHandle::Address & address, @@ -74,6 +72,7 @@ namespace senf { peer \returns file descriptor of new client socket */ private: + static void do_listen(FileHandle handle, unsigned backlog); static int do_accept(FileHandle handle, struct sockaddr * addr, unsigned len); }; diff --git a/Socket/FileHandle.cci b/Socket/FileHandle.cci index a727bee..37c269d 100644 --- a/Socket/FileHandle.cci +++ b/Socket/FileHandle.cci @@ -171,7 +171,7 @@ prefix_ bool senf::FileHandle::eof() prefix_ bool senf::FileHandle::valid() const { - return body().valid(); + return body_ && body().valid(); } prefix_ bool senf::FileHandle::boolean_test() @@ -186,18 +186,24 @@ prefix_ int senf::FileHandle::fd() return body().fd(); } +prefix_ senf::FileHandle::FileHandle() + : body_(0) +{} + prefix_ senf::FileHandle::FileHandle(std::auto_ptr body) : body_(body.release()) {} prefix_ senf::FileBody & senf::FileHandle::body() { + BOOST_ASSERT(body_); return *body_; } prefix_ senf::FileBody const & senf::FileHandle::body() const { + BOOST_ASSERT(body_); return *body_; } diff --git a/Socket/FileHandle.hh b/Socket/FileHandle.hh index 303916b..86cb10f 100644 --- a/Socket/FileHandle.hh +++ b/Socket/FileHandle.hh @@ -28,40 +28,30 @@ \image html FhHierarchy.png - The senf::FileHandle class is the base of a hierarchy of socket - handle classes (realized as templates). These classes provide an - interface to the complete socket API. While going down the - inheritance hierarchy, the interface will be more and more - complete. - - The most complete interface is provided by - senf::ProtocolClientSocketHandle and - senf::ProtocolServerSocketHandle. The template Arguments specifies - the Protocol class of the underlying socket type. These are the - \e only classes having public constructors and are therefore the - only classes, which may be created by the library user. You will - normally use these classes by naming a specific socket typedef - (e.g. senf::TCPv4ClientSocketHandle). - - However, to aid writing flexible and generic code, the socket - library provides the senf::ClientSocketHandle and - senf::ServerSocketHandle class templates. These templates - implement a family of closely related classes based on the - specification of the socket policy. This policy specification may - be \e incomplete (see below). Instances of - senf::ClientSocketHandle/senf::ServerSocketHandle can be assigned - and converted to different ClientSocketHandle/ServerSocketHandle - types as long as the policy specifications are compatible. - - \attention It is very important, to (almost) always pass the socket - handle by value. The socket handle is a very lightweight - class and designed to be used like an ordinary built-in type. This - is very important in combination with the policy interface. - - \note The FileHandle hierarchy below the SocketHandle template is - \e not meant to be user extensible. To add new socket types, you - should introduce new protocol and/or policy classes, the - SocketHandle classes should not be changed. + The senf::FileHandle class is the base of a hierarchy of socket handle classes (realized as + templates). These classes provide an interface to the complete socket API. While going down the + inheritance hierarchy, the interface will be more and more complete. + + The most complete interface is provided by senf::ProtocolClientSocketHandle and + senf::ProtocolServerSocketHandle. The template Arguments specifies the Protocol class of the + underlying socket type. These are the \e only classes having public constructors and are + therefore the only classes, which may be created by the library user. You will normally use + these classes by naming a specific socket typedef (e.g. senf::TCPv4ClientSocketHandle). + + However, to aid writing flexible and generic code, the socket library provides the + senf::ClientSocketHandle and senf::ServerSocketHandle class templates. These templates implement + a family of closely related classes based on the specification of the socket policy. This policy + specification may be \e incomplete (see below). Instances of + senf::ClientSocketHandle/senf::ServerSocketHandle can be assigned and converted to different + ClientSocketHandle/ServerSocketHandle types as long as the policy specifications are compatible. + + \attention It is very important, to (almost) always pass the socket handle by + value. The socket handle is a very lightweight class and designed to be used like an + ordinary built-in type. This is very important in combination with the policy interface. + + \note The FileHandle hierarchy below the SocketHandle template is \e not meant to be user + extensible. To add new socket types, you should introduce new protocol and/or policy classes, + the SocketHandle classes should not be changed. */ #ifndef HH_FileHandle_ @@ -108,9 +98,6 @@ namespace senf { will have to call the protected FileHandle constructor passing a new senf::FileBody instance. This instance may either be a simple senf::FileBody or a class derived from senf::FileBody. - - \fixme Add public default constructor to allow declaration of (empty) senf::FileHandle - variables. */ class FileHandle : public SafeBool @@ -123,7 +110,9 @@ namespace senf { ///\name Structors and default members ///@{ - // protected default constructor + FileHandle(); + + // my default constructor // default copy constructor // default copy assignment // default destructor diff --git a/Socket/FileHandle.test.cc b/Socket/FileHandle.test.cc index 262bf0c..547bdbf 100644 --- a/Socket/FileHandle.test.cc +++ b/Socket/FileHandle.test.cc @@ -41,7 +41,8 @@ namespace { class FHandle : public senf::FileHandle { public: - FHandle(int fd=-1) + FHandle() {} + FHandle(int fd) : senf::FileHandle(std::auto_ptr( new senf::FileBody(fd))) {} FHandle(std::string name) @@ -66,7 +67,9 @@ BOOST_AUTO_UNIT_TEST(fileHandle) BOOST_CHECK(fh); BOOST_CHECK(!!fh); - FHandle fh2(fh); + FHandle fh2; + BOOST_CHECK( ! fh2.valid() ); + fh2 = fh; BOOST_CHECK_EQUAL(fh.fd(), fh2.fd()); BOOST_CHECK(fh.writeable()); diff --git a/Socket/INetAddressing.cci b/Socket/INetAddressing.cci index 8af052f..eb366ef 100644 --- a/Socket/INetAddressing.cci +++ b/Socket/INetAddressing.cci @@ -58,8 +58,8 @@ prefix_ bool senf::INet4Address::operator==(INet4Address const & other) prefix_ std::string senf::INet4Address::host() const { - /** \fixme thread safety? */ - return std::string(::inet_ntoa(addr_.sin_addr)); + char buffer[128]; + return std::string(::inet_ntop(AF_INET,&addr_.sin_addr,buffer,128)); } prefix_ unsigned senf::INet4Address::port() diff --git a/Socket/INetAddressing.hh b/Socket/INetAddressing.hh index de661cb..db2be65 100644 --- a/Socket/INetAddressing.hh +++ b/Socket/INetAddressing.hh @@ -59,9 +59,7 @@ namespace senf { INet4Address(); INet4Address(char const * address); ///< Set address and port /**< See INet4Address(std::string) - \throws InvalidINetAddressException - \fixme Why do I need this version? Shouldn't the - std::string version be enough ? */ + \throws InvalidINetAddressException */ INet4Address(std::string address); ///< Set address and port /**< This constructor expects a string of the form 'xxx.xxx.xxx.xxx:pppp'. The constructor will use this diff --git a/Socket/ProtocolClientSocketHandle.cti b/Socket/ProtocolClientSocketHandle.cti index a3e383e..2123198 100644 --- a/Socket/ProtocolClientSocketHandle.cti +++ b/Socket/ProtocolClientSocketHandle.cti @@ -35,6 +35,11 @@ ///////////////////////////////cti.p/////////////////////////////////////// template +prefix_ senf::ProtocolClientSocketHandle:: +ProtocolClientSocketHandle(UninitializedType) +{} + +template prefix_ senf::ProtocolClientSocketHandle::ProtocolClientSocketHandle() : ClientSocketHandle( std::auto_ptr(new SocketProtocol())) diff --git a/Socket/ProtocolClientSocketHandle.hh b/Socket/ProtocolClientSocketHandle.hh index f9e456d..375db13 100644 --- a/Socket/ProtocolClientSocketHandle.hh +++ b/Socket/ProtocolClientSocketHandle.hh @@ -65,6 +65,7 @@ namespace senf { // Types typedef SocketProtocol Protocol; ///< The sockets protocol + enum UninitializedType { Uninitialized }; ///< Flag to call 'uninitialized' constructor /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -84,6 +85,17 @@ namespace senf { # define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolClientSocketHandle.mpp", 1)) # include BOOST_PP_ITERATE() + /** \brief Create uninitialized socket variable + + This special constructor is called when passing + ProtocolClientSocketHandle::Uninitialized as only argument to the constructor. This will + create an in-\ref valid() socket handle which can however be assigned later with another + socket instance. + + \implementation The socket handle will have no \c body allocated. + */ + ProtocolClientSocketHandle(UninitializedType); + ///@} /////////////////////////////////////////////////////////////////////////// diff --git a/Socket/ProtocolServerSocketHandle.cti b/Socket/ProtocolServerSocketHandle.cti index 9c7a449..67abd4c 100644 --- a/Socket/ProtocolServerSocketHandle.cti +++ b/Socket/ProtocolServerSocketHandle.cti @@ -35,6 +35,11 @@ ///////////////////////////////cti.p/////////////////////////////////////// template +prefix_ senf::ProtocolServerSocketHandle:: +ProtocolServerSocketHandle(UninitializedType) +{} + +template prefix_ senf::ProtocolServerSocketHandle::ProtocolServerSocketHandle() : ServerSocketHandle( std::auto_ptr(new SocketProtocol())) diff --git a/Socket/ProtocolServerSocketHandle.hh b/Socket/ProtocolServerSocketHandle.hh index c4bc01a..af6db47 100644 --- a/Socket/ProtocolServerSocketHandle.hh +++ b/Socket/ProtocolServerSocketHandle.hh @@ -69,6 +69,7 @@ namespace senf { // Types typedef SocketProtocol Protocol; ///< The socket protocol + enum UninitializedType { Uninitialized }; ///< Flag to call 'uninitialized' constructor /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -89,6 +90,16 @@ namespace senf { # define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolServerSocketHandle.mpp", 1)) # include BOOST_PP_ITERATE() + /** \brief Create uninitialized socket variable + + This special constructor is called when passing + ProtocolServerSocketHandle::Uninitialized as only argument to the constructor. This will + create an in-\ref valid() socket handle which can however be assigned later with another + socket instance. + + \implementation The socket handle will have no \c body allocated. + */ + ProtocolServerSocketHandle(UninitializedType); ///@} /////////////////////////////////////////////////////////////////////////// diff --git a/Socket/ServerSocketHandle.cti b/Socket/ServerSocketHandle.cti index 03764f3..1706074 100644 --- a/Socket/ServerSocketHandle.cti +++ b/Socket/ServerSocketHandle.cti @@ -34,6 +34,10 @@ #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// +template +prefix_ senf::ServerSocketHandle::ServerSocketHandle() +{} + template template prefix_ senf::ServerSocketHandle:: diff --git a/Socket/ServerSocketHandle.hh b/Socket/ServerSocketHandle.hh index b096036..76b2510 100644 --- a/Socket/ServerSocketHandle.hh +++ b/Socket/ServerSocketHandle.hh @@ -96,11 +96,14 @@ namespace senf { ///\name Structors and default members ///@{ - // no default constructor + // default default constructor // default copy constructor // default copy assignment // default destructor + // here to implement + ServerSocketHandle(); + // conversion constructors template ServerSocketHandle(ServerSocketHandle other, diff --git a/Socket/SocketHandle.cti b/Socket/SocketHandle.cti index 56c1472..3df213c 100644 --- a/Socket/SocketHandle.cti +++ b/Socket/SocketHandle.cti @@ -35,6 +35,10 @@ ///////////////////////////////cti.p/////////////////////////////////////// template +prefix_ senf::SocketHandle::SocketHandle() +{} + +template template prefix_ senf::SocketHandle::SocketHandle(SocketHandle other, typename IsCompatible::type *) diff --git a/Socket/SocketHandle.hh b/Socket/SocketHandle.hh index 8cd567f..ce67d0e 100644 --- a/Socket/SocketHandle.hh +++ b/Socket/SocketHandle.hh @@ -89,10 +89,14 @@ namespace senf { ///\name Structors and default members ///@{ + // default default constructor // default copy constructor // default copy assignment // default destructor + // here to implement + SocketHandle(); + // conversion constructors template