# HG changeset patch # User David Demelier # Date 1430309098 -7200 # Node ID f3c7625790736b8190d0ed0827eff18a963562e1 # Parent 6c0015524ca92208c3681873e3cde9ff5cc10945 Socket: add more docs into SocketListener diff -r 6c0015524ca9 -r f3c762579073 C++/modules/Socket/SocketListener.cpp --- a/C++/modules/Socket/SocketListener.cpp Wed Apr 29 13:51:24 2015 +0200 +++ b/C++/modules/Socket/SocketListener.cpp Wed Apr 29 14:04:58 2015 +0200 @@ -138,36 +138,31 @@ return flags; } -void Poll::set(Socket s, int flags, bool) +void Poll::set(Socket s, int flags, bool add) { - auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const auto &pfd) { - return pfd.fd == s.handle(); - }); + if (add) { + m_lookup.emplace(s.handle(), s); + m_fds.push_back(pollfd{s.handle(), topoll(flags), 0}); + } else { + auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const struct pollfd &pfd) { + return pfd.fd == s.handle(); + }); - // If found, add the new flags, otherwise add a new socket - if (it != m_fds.end()) { it->events |= topoll(flags); - } else { - m_lookup.emplace(s.handle(), s); - m_fds.push_back({ s.handle(), topoll(flags), 0 }); } } -void Poll::unset(Socket s, int flags, bool) +void Poll::unset(Socket s, int flags, bool remove) { - for (auto i = m_fds.begin(); i != m_fds.end();) { - if (i->fd == s.handle()) { - i->events &= ~(topoll(flags)); + auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const struct pollfd &pfd) { + return pfd.fd == s.handle(); + }); - if (i->events == 0) { - m_lookup.erase(i->fd); - i = m_fds.erase(i); - } else { - ++i; - } - } else { - ++i; - } + if (remove) { + m_lookup.erase(it->fd); + m_fds.erase(it); + } else { + it->events &= ~(topoll(flags)); } } diff -r 6c0015524ca9 -r f3c762579073 C++/modules/Socket/SocketListener.h --- a/C++/modules/Socket/SocketListener.h Wed Apr 29 13:51:24 2015 +0200 +++ b/C++/modules/Socket/SocketListener.h Wed Apr 29 14:04:58 2015 +0200 @@ -127,18 +127,12 @@ /* * No-op, uses the SocketTable directly. */ - inline void set(Socket, int, bool) noexcept - { - - } + inline void set(Socket, int, bool) noexcept {} /* * No-op, uses the SocketTable directly. */ - inline void unset(Socket, int, bool) noexcept - { - - } + inline void unset(Socket, int, bool) noexcept {} SocketStatus wait(const SocketTable &table, int ms); std::vector waitMultiple(const SocketTable &table, int ms); @@ -171,7 +165,6 @@ #endif #if defined(SOCKET_HAVE_EPOLL) - #endif #if defined(SOCKET_HAVE_KQUEUE) @@ -223,6 +216,34 @@ * you can safely modify on the fly. * * Currently, poll, select and kqueue are available. + * + * To implement the backend, the following functions must be available: + * + * # Set + * + * @code + * void set(Socket sc, int flags, bool add); + * @endcode + * + * This function, takes the socket to be added and the flags. The flags are + * always guaranteed to be correct and the function will never be called twice + * even if the user tries to set the same flag again. + * + * An optional add argument is added for backends which needs to do different + * operation depending if the socket was already set before or if it is the + * first time (e.g EPOLL_CTL_ADD vs EPOLL_CTL_MOD for epoll(7). + * + * # Unset + * + * @code + * void unset(Socket sc, int flags, bool remove); + * @endcode + * + * Like set, this function is only called if the flags are actually set and will + * not be called multiple times. + * + * Also like set, an optional remove argument is set if the socket is being + * completely removed (e.g no more flags are set for this socket). */ template class SocketListenerBase final { @@ -235,6 +256,9 @@ SocketTable m_table; public: + /** + * Construct an empty listener. + */ inline SocketListenerBase() { } diff -r 6c0015524ca9 -r f3c762579073 C++/tests/Socket/main.cpp --- a/C++/tests/Socket/main.cpp Wed Apr 29 13:51:24 2015 +0200 +++ b/C++/tests/Socket/main.cpp Wed Apr 29 14:04:58 2015 +0200 @@ -387,13 +387,11 @@ ASSERT_EQ(1U, listener.size()); } -#if 0 - /* -------------------------------------------------------- - * Listener: select + * Listener: system * -------------------------------------------------------- */ -class ListenerSelectTest : public testing::Test { +class ListenerTest : public testing::Test { protected: SocketListenerBase m_listener; SocketTcp m_masterTcp{AF_INET, 0}; @@ -403,14 +401,14 @@ std::thread m_tclient; public: - ListenerSelectTest() + ListenerTest() { m_masterTcp.set(SOL_SOCKET, SO_REUSEADDR, 1); m_masterTcp.bind(Internet("*", 16000, AF_INET)); m_masterTcp.listen(); } - ~ListenerSelectTest() + ~ListenerTest() { if (m_tserver.joinable()) { m_tserver.join(); @@ -421,7 +419,7 @@ } }; -TEST_F(ListenerSelectTest, accept) +TEST_F(ListenerTest, accept) { m_tserver = std::thread([this] () { try { @@ -441,7 +439,7 @@ }); } -TEST_F(ListenerSelectTest, recv) +TEST_F(ListenerTest, recv) { m_tserver = std::thread([this] () { try { @@ -466,8 +464,6 @@ }); } -#endif - /* -------------------------------------------------------- * Non-blocking connect * -------------------------------------------------------- */