# HG changeset patch # User David Demelier # Date 1427988771 -7200 # Node ID d235553e47a9fb835c6e20bc7a5cb09522fea42d # Parent c293dbe181c00ff8a007b247afebb389051eae06 Socket: - SocketListener is now implemented as a template and use the backend as the template parameter. No more virtual implementation, - Improve backend detection and set the default backend implementation automatically, - Rename Socket::init to Socket::initialize for non-Windows systems, - Rename SocketListener::(select|selectMultiple) to wait|waitMultiple - Coming up soon: kqueue and epoll backends. diff -r c293dbe181c0 -r d235553e47a9 C++/modules/Socket/Socket.h --- a/C++/modules/Socket/Socket.h Tue Mar 31 09:57:37 2015 +0200 +++ b/C++/modules/Socket/Socket.h Thu Apr 02 17:32:51 2015 +0200 @@ -238,7 +238,7 @@ /** * no-op. */ - static inline void init() noexcept {} + static inline void initialize() noexcept {} /** * no-op. diff -r c293dbe181c0 -r d235553e47a9 C++/modules/Socket/SocketListener.cpp --- a/C++/modules/Socket/SocketListener.cpp Tue Mar 31 09:57:37 2015 +0200 +++ b/C++/modules/Socket/SocketListener.cpp Thu Apr 02 17:32:51 2015 +0200 @@ -28,116 +28,102 @@ * Select implementation * -------------------------------------------------------- */ -namespace { +namespace backend { + +void Select::set(Socket &s, int direction) +{ + if (m_table.count(s.handle()) > 0) { + m_table.at(s.handle()).second |= direction; + } else { + m_table.insert({s.handle(), {s, direction}}); + } + +} + +void Select::unset(Socket &s, int direction) +{ + if (m_table.count(s.handle()) != 0) { + m_table.at(s.handle()).second &= ~(direction); + + // If no read, no write is requested, remove it + if (m_table.at(s.handle()).second == 0) { + m_table.erase(s.handle()); + } + } +} + +void Select::remove(Socket &sc) +{ + m_table.erase(sc.handle()); +} -/** - * @class SelectMethod - * @brief Implements select(2) - * - * This class is the fallback of any other method, it is not preferred at all for many reasons. - */ -class SelectMethod final : public SocketListenerInterface { -private: - std::map, int>> m_table; +void Select::clear() +{ + m_table.clear(); +} + +SocketStatus Select::wait(int ms) +{ + auto result = waitMultiple(ms); + + if (result.size() == 0) { + throw SocketError(SocketError::System, "select", "No socket found"); + } + + return result[0]; +} -public: - void set(Socket &s, int direction) override - { - if (m_table.count(s.handle()) > 0) { - m_table.at(s.handle()).second |= direction; - } else { - m_table.insert({s.handle(), {s, direction}}); +std::vector Select::waitMultiple(int ms) +{ + timeval maxwait, *towait; + fd_set readset; + fd_set writeset; + + FD_ZERO(&readset); + FD_ZERO(&writeset); + + Socket::Handle max = 0; + + for (auto &s : m_table) { + if (s.second.second & SocketListener::Read) { + FD_SET(s.first, &readset); + } + if (s.second.second & SocketListener::Write) { + FD_SET(s.first, &writeset); } - } - - void unset(Socket &s, int direction) override - { - if (m_table.count(s.handle()) != 0) { - m_table.at(s.handle()).second &= ~(direction); - - // If no read, no write is requested, remove it - if (m_table.at(s.handle()).second == 0) { - m_table.erase(s.handle()); - } + if (s.first > max) { + max = s.first; } } - void remove(Socket &sc) override - { - m_table.erase(sc.handle()); - } + maxwait.tv_sec = 0; + maxwait.tv_usec = ms * 1000; - void clear() override - { - m_table.clear(); - } + // Set to nullptr for infinite timeout. + towait = (ms < 0) ? nullptr : &maxwait; - SocketStatus select(int ms) override - { - auto result = selectMultiple(ms); - - if (result.size() == 0) { - throw SocketError(SocketError::System, "select", "No socket found"); - } - - return result[0]; + auto error = ::select(max + 1, &readset, &writeset, nullptr, towait); + if (error == Socket::Error) { + throw SocketError(SocketError::System, "select"); + } + if (error == 0) { + throw SocketError(SocketError::Timeout, "select", "Timeout while listening"); } - std::vector selectMultiple(int ms) override - { - timeval maxwait, *towait; - fd_set readset; - fd_set writeset; - - FD_ZERO(&readset); - FD_ZERO(&writeset); - - Socket::Handle max = 0; - - for (auto &s : m_table) { - if (s.second.second & SocketListener::Read) { - FD_SET(s.first, &readset); - } - if (s.second.second & SocketListener::Write) { - FD_SET(s.first, &writeset); - } - - if (s.first > max) { - max = s.first; - } - } - - maxwait.tv_sec = 0; - maxwait.tv_usec = ms * 1000; + std::vector sockets; - // Set to nullptr for infinite timeout. - towait = (ms < 0) ? nullptr : &maxwait; - - auto error = ::select(max + 1, &readset, &writeset, nullptr, towait); - if (error == Socket::Error) { - throw SocketError(SocketError::System, "select"); + for (auto &c : m_table) { + if (FD_ISSET(c.first, &readset)) { + sockets.push_back({ c.second.first, SocketListener::Read }); } - if (error == 0) { - throw SocketError(SocketError::Timeout, "select", "Timeout while listening"); + if (FD_ISSET(c.first, &writeset)) { + sockets.push_back({ c.second.first, SocketListener::Write }); } - - std::vector sockets; + } - for (auto &c : m_table) { - if (FD_ISSET(c.first, &readset)) { - sockets.push_back({ c.second.first, SocketListener::Read }); - } - if (FD_ISSET(c.first, &writeset)) { - sockets.push_back({ c.second.first, SocketListener::Write }); - } - } - - return sockets; - } -}; - -} // !namespace + return sockets; +} /* -------------------------------------------------------- * Poll implementation @@ -146,193 +132,130 @@ #if defined(SOCKET_HAVE_POLL) #if defined(_WIN32) -# include # define poll WSAPoll -#else -# include #endif -namespace { - -class PollMethod final : public SocketListenerInterface { -private: - std::vector m_fds; - std::map> m_lookup; +short Poll::topoll(int direction) const noexcept +{ + short result(0); - inline short topoll(int direction) - { - short result(0); - - if (direction & SocketListener::Read) { - result |= POLLIN; - } - if (direction & SocketListener::Write) { - result |= POLLOUT; - } - - return result; + if (direction & SocketListener::Read) { + result |= POLLIN; + } + if (direction & SocketListener::Write) { + result |= POLLOUT; } - inline int todirection(short event) - { - int direction{}; + return result; +} + +int Poll::todirection(short event) const noexcept +{ + int direction{}; - /* - * Poll implementations mark the socket differently regarding - * the disconnection of a socket. - * - * At least, even if POLLHUP or POLLIN is set, recv() always - * return 0 so we mark the socket as readable. - */ - if ((event & POLLIN) || (event & POLLHUP)) { - direction |= SocketListener::Read; - } - if (event & POLLOUT) { - direction |= SocketListener::Write; - } - - return direction; + /* + * Poll implementations mark the socket differently regarding + * the disconnection of a socket. + * + * At least, even if POLLHUP or POLLIN is set, recv() always + * return 0 so we mark the socket as readable. + */ + if ((event & POLLIN) || (event & POLLHUP)) { + direction |= SocketListener::Read; + } + if (event & POLLOUT) { + direction |= SocketListener::Write; } -public: - void set(Socket &s, int direction) override - { - auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const auto &pfd) { return pfd.fd == s.handle(); }); + return direction; +} + +void Poll::set(Socket &s, int direction) override +{ + auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const auto &pfd) { return pfd.fd == s.handle(); }); - // If found, add the new direction, otherwise add a new socket - if (it != m_fds.end()) { - it->events |= topoll(direction); - } else { - m_lookup.insert({s.handle(), s}); - m_fds.push_back({ s.handle(), topoll(direction), 0 }); - } + // If found, add the new direction, otherwise add a new socket + if (it != m_fds.end()) { + it->events |= topoll(direction); + } else { + m_lookup.insert({s.handle(), s}); + m_fds.push_back({ s.handle(), topoll(direction), 0 }); } - - void unset(Socket &s, int direction) override - { - for (auto i = m_fds.begin(); i != m_fds.end();) { - if (i->fd == s.handle()) { - i->events &= ~(topoll(direction)); +} - if (i->events == 0) { - m_lookup.erase(i->fd); - i = m_fds.erase(i); - } else { - ++i; - } +void Poll::unset(Socket &s, int direction) override +{ + for (auto i = m_fds.begin(); i != m_fds.end();) { + if (i->fd == s.handle()) { + i->events &= ~(topoll(direction)); + + if (i->events == 0) { + m_lookup.erase(i->fd); + i = m_fds.erase(i); } else { ++i; } + } else { + ++i; } } +} + +void Poll::remove(Socket &s) override +{ + auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const auto &pfd) { return pfd.fd == s.handle(); }); + + if (it != m_fds.end()) { + m_fds.erase(it); + m_lookup.erase(s.handle()); + } +} + +void Poll::clear() override +{ + m_fds.clear(); + m_lookup.clear(); +} + +SocketStatus Poll::wait(int ms) override +{ + auto result = poll(m_fds.data(), m_fds.size(), ms); + if (result == 0) { + throw SocketError(SocketError::Timeout, "select", "Timeout while listening"); + } + if (result < 0) { + throw SocketError(SocketError::System, "poll"); + } - void remove(Socket &s) override - { - auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const auto &pfd) { return pfd.fd == s.handle(); }); - - if (it != m_fds.end()) { - m_fds.erase(it); - m_lookup.erase(s.handle()); + for (auto &fd : m_fds) { + if (fd.revents != 0) { + return { m_lookup.at(fd.fd), todirection(fd.revents) }; } } - void clear() override - { - m_fds.clear(); - m_lookup.clear(); + throw SocketError(SocketError::System, "select", "No socket found"); +} + +std::vector Poll::waitMultiple(int ms) override +{ + auto result = poll(m_fds.data(), m_fds.size(), ms); + if (result == 0) { + throw SocketError(SocketError::Timeout, "select", "Timeout while listening"); + } + if (result < 0) { + throw SocketError(SocketError::System, "poll"); } - SocketStatus select(int ms) override - { - auto result = poll(m_fds.data(), m_fds.size(), ms); - if (result == 0) { - throw SocketError(SocketError::Timeout, "select", "Timeout while listening"); - } - if (result < 0) { - throw SocketError(SocketError::System, "poll"); + std::vector sockets; + for (auto &fd : m_fds) { + if (fd.revents != 0) { + sockets.push_back({ m_lookup.at(fd.fd), todirection(fd.revents) }); } - - for (auto &fd : m_fds) { - if (fd.revents != 0) { - return { m_lookup.at(fd.fd), todirection(fd.revents) }; - } - } - - throw SocketError(SocketError::System, "select", "No socket found"); } - std::vector selectMultiple(int ms) override - { - auto result = poll(m_fds.data(), m_fds.size(), ms); - if (result == 0) { - throw SocketError(SocketError::Timeout, "select", "Timeout while listening"); - } - if (result < 0) { - throw SocketError(SocketError::System, "poll"); - } - - std::vector sockets; - for (auto &fd : m_fds) { - if (fd.revents != 0) { - sockets.push_back({ m_lookup.at(fd.fd), todirection(fd.revents) }); - } - } - - return sockets; - } -}; - -} // !namespace + return sockets; +} #endif // !_SOCKET_HAVE_POLL -/* -------------------------------------------------------- - * SocketListener - * -------------------------------------------------------- */ - -const int SocketListener::Read{1 << 0}; -const int SocketListener::Write{1 << 1}; - -SocketListener::SocketListener(std::initializer_list, int>> list) - : SocketListener() -{ - for (const auto &p : list) { - set(p.first, p.second); - } -} - -SocketListener::SocketListener(SocketMethod method) -{ -#if defined(SOCKET_HAVE_POLL) - if (method == SocketMethod::Poll) - m_interface = std::make_unique(); - else -#endif - m_interface = std::make_unique(); - - (void)method; -} - -void SocketListener::set(Socket &sc, int flags) -{ - if (m_map.count(sc) > 0) { - m_map[sc] |= flags; - m_interface->set(sc, flags); - } else { - m_map.insert({sc, flags}); - m_interface->set(sc, flags); - } -} - -void SocketListener::unset(Socket &sc, int flags) noexcept -{ - if (m_map.count(sc) > 0) { - m_map[sc] &= ~(flags); - m_interface->unset(sc, flags); - - // No more flags, remove it - if (m_map[sc] == 0) { - m_map.erase(sc); - } - } -} +} // !backend \ No newline at end of file diff -r c293dbe181c0 -r d235553e47a9 C++/modules/Socket/SocketListener.h --- a/C++/modules/Socket/SocketListener.h Tue Mar 31 09:57:37 2015 +0200 +++ b/C++/modules/Socket/SocketListener.h Thu Apr 02 17:32:51 2015 +0200 @@ -19,6 +19,62 @@ #ifndef _SOCKET_LISTENER_NG_H_ #define _SOCKET_LISTENER_NG_H_ +/** + * Feature detection, multiple implementations may be avaible, for example, + * Linux has poll, select and epoll. + * + * We assume that select(2) is always available. + * + * Of course, you can set the variables yourself if you test it with your + * build system. + * + * SOCKET_HAVE_POLL - Defined on all BSD, Linux. Also defined on Windows + * if _WIN32_WINNT is set to 0x0600 or greater. + * SOCKET_HAVE_KQUEUE - Defined on all BSD and Apple. + * SOCKET_HAVE_EPOLL - Defined on Linux only. + */ +#if defined(_WIN32) +# if _WIN32_WINNT >= 0x0600 +# define SOCKET_HAVE_POLL +# endif +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +# define SOCKET_HAVE_KQUEUE +# define SOCKET_HAVE_POLL +#elif defined(__linux__) +# define SOCKET_HAVE_EPOLL +# define SOCKET_HAVE_POLL +#endif + +/** + * This sets the default backend to use depending on the system. The following + * table summaries. + * + * The preference priority is ordered from left to right. + * + * +---------------+-------------------------+ + * | System | Backend | + * +---------------+-------------------------+ + * | Linux | epoll(2) | + * | *BSD | kqueue(2) | + * | Windows | poll(2), select(2) | + * | Mac OS X | kqueue(2) | + * +---------------+-------------------------+ + */ + +#if defined(_WIN32) +# if defined(SOCKET_HAVE_POLL) +# define SOCKET_DEFAULT_BACKEND backend::Poll +# else +# define SOCKET_DEFAULT_BACKEND backend::Select +# endif +#elif defined(__linux__) +# define SOCKET_DEFAULT_BACKEND backend::Epoll +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +# define SOCKET_DEFAULT_BACKEND backend::Kqueue +#else +# define SOCKET_DEFAULT_BACKEND backend::Select +#endif + #include #include #include @@ -29,101 +85,85 @@ #include "Socket.h" -#if defined(_WIN32) -# if _WIN32_WINNT >= 0x0600 -# define SOCKET_HAVE_POLL -# endif -#else -# define SOCKET_HAVE_POLL +#if defined(SOCKET_HAVE_POLL) +# include #endif /** - * @enum SocketMethod - * @brief The SocketMethod enum - * - * Select the method of polling. It is only a preferred method, for example if you - * request for poll but it is not available, select will be used. - */ -enum class SocketMethod { - Select, //!< select(2) method, fallback - Poll //!< poll(2), everywhere possible -}; - -/** * @struct SocketStatus * @brief The SocketStatus struct * * Result of a select call, returns the first ready socket found with its - * direction. + * flags. */ class SocketStatus { public: Socket &socket; //!< which socket is ready - int direction; //!< the direction + int flags; //!< the flags }; +namespace backend { + /** - * @class SocketListenerInterface - * @brief Implement the polling method + * @class Select + * @brief Implements select(2) + * + * This class is the fallback of any other method, it is not preferred at all for many reasons. */ -class SocketListenerInterface { -public: - /** - * Default destructor. - */ - virtual ~SocketListenerInterface() = default; - - /** - * Add a socket with a specified direction. - * - * @param s the socket - * @param direction the direction - */ - virtual void set(Socket &sc, int direction) = 0; - - /** - * Remove a socket with a specified direction. - * - * @param s the socket - * @param direction the direction - */ - virtual void unset(Socket &sc, int direction) = 0; +class Select { +private: + std::map, int>> m_table; - /** - * Remove completely a socket. - * - * @param sc the socket to remove - */ - virtual void remove(Socket &sc) = 0; - - /** - * Remove all sockets. - */ - virtual void clear() = 0; - - /** - * Select one socket. - * - * @param ms the number of milliseconds to wait, -1 means forever - * @return the socket status - * @throw error::Failure on failure - * @throw error::Timeout on timeout - */ - virtual SocketStatus select(int ms) = 0; - - /** - * Select many sockets. - * - * @param ms the number of milliseconds to wait, -1 means forever - * @return a vector of ready sockets - * @throw error::Failure on failure - * @throw error::Timeout on timeout - */ - virtual std::vector selectMultiple(int ms) = 0; +public: + void set(Socket &s, int direction); + void unset(Socket &s, int direction); + void remove(Socket &sc); + void clear(); + SocketStatus wait(int ms); + std::vector waitMultiple(int ms); }; +#if defined(SOCKET_HAVE_POLL) + +class Poll { +private: + std::vector m_fds; + std::map> m_lookup; + + short topoll(int direction) const noexcept; + int todirection(short event) const noexcept; + +public: + void set(Socket &s, int direction); + void unset(Socket &s, int direction); + void remove(Socket &sc); + void clear(); + SocketStatus wait(int ms); + std::vector waitMultiple(int ms); +}; + +#endif + +#if defined(SOCKET_HAVE_EPOLL) + +class Epoll { + // TODO +}; + +#endif + +#if defined(SOCKET_HAVE_KQUEUE) + +class Kqueue { + // TODO +}; + +#endif + +} // !backend + /** - * @class SocketListener + * @class SocketListenerBase * @brief Synchronous multiplexing * * Convenient wrapper around the select() system call. @@ -137,25 +177,20 @@ * own them so you must take care that sockets are still alive until the * SocketListener is destroyed. */ -class SocketListener final { +template +class SocketListenerBase final { public: -#if defined(SOCKET_HAVE_POLL) - static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll; -#else - static constexpr const SocketMethod PreferredMethod = SocketMethod::Select; -#endif - static const int Read; static const int Write; using Map = std::map, int>; - using Iface = std::unique_ptr; private: + Backend m_backend; Map m_map; - Iface m_interface; public: +#if 0 /** * Move constructor. * @@ -170,20 +205,22 @@ * @return this */ SocketListener &operator=(SocketListener &&other) = default; - - /** - * Create a socket listener. - * - * @param method the preferred method - */ - SocketListener(SocketMethod method = PreferredMethod); +#endif + inline SocketListenerBase() + { + } /** * Create a listener from a list of sockets. * * @param list the list */ - SocketListener(std::initializer_list, int>> list); + inline SocketListenerBase(std::initializer_list, int>> list) + { + for (const auto &p : list) { + set(p.first, p.second); + } + } /** * Return an iterator to the beginning. @@ -249,9 +286,18 @@ * Add a socket to the listener. * * @param sc the socket - * @param direction (may be OR'ed) + * @param flags (may be OR'ed) */ - void set(Socket &sc, int direction); + void set(Socket &sc, int flags) + { + if (m_map.count(sc) > 0) { + m_map[sc] |= flags; + m_backend.set(sc, flags); + } else { + m_map.insert({sc, flags}); + m_backend.set(sc, flags); + } + } /** * Unset a socket from the listener, only the direction is removed @@ -261,10 +307,21 @@ * unsetting the write direction will keep the socket for reading. * * @param sc the socket - * @param direction the direction (may be OR'ed) + * @param flags the flags (may be OR'ed) * @see remove */ - void unset(Socket &sc, int direction) noexcept; + void unset(Socket &sc, int flags) noexcept + { + if (m_map.count(sc) > 0) { + m_map[sc] &= ~(flags); + m_backend.unset(sc, flags); + + // No more flags, remove it + if (m_map[sc] == 0) { + m_map.erase(sc); + } + } + } /** * Remove completely the socket from the listener. @@ -274,7 +331,7 @@ inline void remove(Socket &sc) noexcept { m_map.erase(sc); - m_interface->remove(sc); + m_backend.remove(sc); } /** @@ -283,7 +340,7 @@ inline void clear() noexcept { m_map.clear(); - m_interface->clear(); + m_backend.clear(); } /** @@ -301,11 +358,11 @@ * @return the socket ready */ template - inline SocketStatus select(const std::chrono::duration &duration) + inline SocketStatus wait(const std::chrono::duration &duration) { auto cvt = std::chrono::duration_cast(duration); - return m_interface->select(cvt.count()); + return m_backend.wait(cvt.count()); } /** @@ -314,9 +371,9 @@ * @param timeout the optional timeout in milliseconds * @return the socket ready */ - inline SocketStatus select(int timeout = -1) + inline SocketStatus wait(int timeout = -1) { - return m_interface->select(timeout); + return m_backend.wait(timeout); } /** @@ -326,11 +383,11 @@ * @return the socket ready */ template - inline std::vector selectMultiple(const std::chrono::duration &duration) + inline std::vector waitMultiple(const std::chrono::duration &duration) { auto cvt = std::chrono::duration_cast(duration); - return m_interface->selectMultiple(cvt.count()); + return m_backend.waitMultiple(cvt.count()); } /** @@ -338,10 +395,21 @@ * * @return the socket ready */ - inline std::vector selectMultiple(int timeout = -1) + inline std::vector waitMultiple(int timeout = -1) { - return m_interface->selectMultiple(timeout); + return m_backend.waitMultiple(timeout); } }; +/** + * Helper to use the default. + */ +using SocketListener = SocketListenerBase<>; + +template +const int SocketListenerBase::Read{1 << 0}; + +template +const int SocketListenerBase::Write{1 << 1}; + #endif // !_SOCKET_LISTENER_NG_H_ diff -r c293dbe181c0 -r d235553e47a9 C++/modules/Socket/SocketSsl.cpp --- a/C++/modules/Socket/SocketSsl.cpp Tue Mar 31 09:57:37 2015 +0200 +++ b/C++/modules/Socket/SocketSsl.cpp Thu Apr 02 17:32:51 2015 +0200 @@ -119,7 +119,7 @@ if (ex.code() == SocketError::WouldBlockRead || ex.code() == SocketError::WouldBlockWrite) { SocketListener listener{{*this, toDirection(ex.code())}}; - listener.select(timeout); + listener.wait(timeout); // Second try connect(address); @@ -195,7 +195,7 @@ { SocketListener listener{{*this, SocketListener::Read}}; - listener.select(timeout); + listener.wait(timeout); return recv(data, len); } @@ -223,7 +223,7 @@ { SocketListener listener{{*this, SocketListener::Write}}; - listener.select(timeout); + listener.wait(timeout); return send(data, len); } diff -r c293dbe181c0 -r d235553e47a9 C++/modules/Socket/SocketTcp.cpp --- a/C++/modules/Socket/SocketTcp.cpp Tue Mar 31 09:57:37 2015 +0200 +++ b/C++/modules/Socket/SocketTcp.cpp Thu Apr 02 17:32:51 2015 +0200 @@ -133,7 +133,7 @@ if (ex.code() == SocketError::WouldBlockWrite) { SocketListener listener{{*this, SocketListener::Write}}; - listener.select(timeout); + listener.wait(timeout); // Socket is writable? Check if there is an error @@ -161,7 +161,7 @@ { SocketListener listener{{*this, SocketListener::Read}}; - listener.select(timeout); + listener.wait(timeout); return accept(info); } @@ -198,7 +198,7 @@ { SocketListener listener{{*this, SocketListener::Read}}; - listener.select(timeout); + listener.wait(timeout); return recv(data, length); } @@ -233,7 +233,7 @@ { SocketListener listener{{*this, SocketListener::Write}}; - listener.select(timeout); + listener.wait(timeout); return send(data, length); } diff -r c293dbe181c0 -r d235553e47a9 C++/tests/Socket/main.cpp --- a/C++/tests/Socket/main.cpp Tue Mar 31 09:57:37 2015 +0200 +++ b/C++/tests/Socket/main.cpp Thu Apr 02 17:32:51 2015 +0200 @@ -174,7 +174,7 @@ class ListenerTest : public testing::Test { protected: - SocketListener m_listener; + SocketListenerBase m_listener; SocketTcp socket1{AF_INET, 0}; SocketUdp socket2{AF_INET, 0}; @@ -266,7 +266,7 @@ class ListenerPollTest : public testing::Test { protected: - SocketListener m_listener{SocketMethod::Poll}; + SocketListener m_listener; SocketTcp m_masterTcp{AF_INET, 0}; SocketTcp m_clientTcp{AF_INET, 0}; @@ -317,7 +317,7 @@ m_tserver = std::thread([this] () { try { m_listener.set(m_masterTcp, SocketListener::Read); - m_listener.select(); + m_listener.wait(); auto sc = m_masterTcp.accept(); @@ -345,7 +345,7 @@ class ListenerSelectTest : public testing::Test { protected: - SocketListener m_listener{SocketMethod::Select}; + SocketListenerBase m_listener; SocketTcp m_masterTcp{AF_INET, 0}; SocketTcp m_clientTcp{AF_INET, 0}; @@ -376,7 +376,7 @@ m_tserver = std::thread([this] () { try { m_listener.set(m_masterTcp, SocketListener::Read); - m_listener.select(); + m_listener.wait(); m_masterTcp.accept(); m_masterTcp.close(); } catch (const std::exception &ex) { @@ -396,7 +396,7 @@ m_tserver = std::thread([this] () { try { m_listener.set(m_masterTcp, SocketListener::Read); - m_listener.select(); + m_listener.wait(); auto sc = m_masterTcp.accept();