Mercurial > code
changeset 353:f1a333e2d2a1
Socket: SocketListener now owns base Socket class
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 28 Apr 2015 07:52:45 +0200 |
parents | 7fe8d4094983 |
children | 5f38366c7654 |
files | C++/modules/Socket/SocketListener.cpp C++/modules/Socket/SocketListener.h tools/CMakeLists.txt |
diffstat | 3 files changed, 45 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/modules/Socket/SocketListener.cpp Wed Apr 08 12:33:45 2015 +0200 +++ b/C++/modules/Socket/SocketListener.cpp Tue Apr 28 07:52:45 2015 +0200 @@ -30,7 +30,7 @@ namespace backend { -void Select::set(Socket &s, int direction) +void Select::set(Socket s, int direction) { if (m_table.count(s.handle()) > 0) { m_table.at(s.handle()).second |= direction; @@ -40,7 +40,7 @@ } -void Select::unset(Socket &s, int direction) +void Select::unset(Socket s, int direction) { if (m_table.count(s.handle()) != 0) { m_table.at(s.handle()).second &= ~(direction); @@ -52,7 +52,7 @@ } } -void Select::remove(Socket &sc) +void Select::remove(Socket sc) { m_table.erase(sc.handle()); } @@ -151,7 +151,7 @@ int Poll::todirection(short event) const noexcept { - int direction{}; + int direction = 0; /* * Poll implementations mark the socket differently regarding @@ -170,7 +170,7 @@ return direction; } -void Poll::set(Socket &s, int direction) +void Poll::set(Socket s, int direction) { auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const auto &pfd) { return pfd.fd == s.handle(); }); @@ -183,7 +183,7 @@ } } -void Poll::unset(Socket &s, int direction) +void Poll::unset(Socket s, int direction) { for (auto i = m_fds.begin(); i != m_fds.end();) { if (i->fd == s.handle()) { @@ -201,7 +201,7 @@ } } -void Poll::remove(Socket &s) +void Poll::remove(Socket s) { auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const auto &pfd) { return pfd.fd == s.handle(); }); @@ -278,7 +278,7 @@ }); } -std::vector<struct kevent>::iterator Kqueue::find(Socket &s) +std::vector<struct kevent>::iterator Kqueue::find(const Socket &s) { return std::find_if(m_list.begin(), m_list.end(), [&] (struct kevent &kv) -> bool { return static_cast<Socket::Handle>(kv.ident) == s.handle(); @@ -306,7 +306,7 @@ m_result.resize(m_list.size()); } -void Kqueue::unset(Socket &s, int direction) +void Kqueue::unset(Socket s, int direction) { auto it = find(s); @@ -325,7 +325,7 @@ } } -void Kqueue::remove(Socket &s) +void Kqueue::remove(Socket s) { auto it = find(s); @@ -364,7 +364,7 @@ if (nevents == 0) { throw SocketError(SocketError::Timeout, "kevent"); } - if (nevents < 0) { + if (nevents < 0) { throw SocketError(SocketError::System, "kevent"); } @@ -373,7 +373,7 @@ *static_cast<Socket *>(m_result[i].udata), (m_result[i].filter & EVFILT_READ) ? SocketListener::Read : SocketListener::Write }); - } + } return sockets; }
--- a/C++/modules/Socket/SocketListener.h Wed Apr 08 12:33:45 2015 +0200 +++ b/C++/modules/Socket/SocketListener.h Tue Apr 28 07:52:45 2015 +0200 @@ -29,7 +29,7 @@ * build system. * * SOCKET_HAVE_POLL - Defined on all BSD, Linux. Also defined on Windows - * if _WIN32_WINNT is set to 0x0600 or greater. + * 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. */ @@ -97,15 +97,15 @@ /** * @struct SocketStatus - * @brief The SocketStatus struct + * @brief The SocketStatus class * * Result of a select call, returns the first ready socket found with its * flags. */ class SocketStatus { public: - Socket &socket; //!< which socket is ready - int flags; //!< the flags + Socket socket; //!< which socket is ready + int flags; //!< the flags }; namespace backend { @@ -118,12 +118,12 @@ */ class Select { private: - std::map<Socket::Handle, std::pair<std::reference_wrapper<Socket>, int>> m_table; + std::map<Socket::Handle, std::pair<Socket, int>> m_table; public: - void set(Socket &s, int direction); - void unset(Socket &s, int direction); - void remove(Socket &sc); + void set(Socket s, int direction); + void unset(Socket s, int direction); + void remove(Socket sc); void clear(); SocketStatus wait(int ms); std::vector<SocketStatus> waitMultiple(int ms); @@ -131,18 +131,25 @@ #if defined(SOCKET_HAVE_POLL) +/** + * @class Poll + * @brief Implements poll(2) + * + * Poll is widely supported and is better than select(2). It is still not the + * best option as selecting the sockets is O(n). + */ class Poll { private: std::vector<pollfd> m_fds; - std::map<Socket::Handle, std::reference_wrapper<Socket>> m_lookup; + std::map<Socket::Handle, Socket> 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 set(Socket s, int direction); + void unset(Socket s, int direction); + void remove(Socket sc); void clear(); SocketStatus wait(int ms); std::vector<SocketStatus> waitMultiple(int ms); @@ -160,6 +167,13 @@ #if defined(SOCKET_HAVE_KQUEUE) +/** + * @class Kqueue + * @brief Implements kqueue(2) + * + * This implementation is available on all BSD and Mac OS X. It is better than + * poll(2) because it's O(1), however it's a bit more memory consuming. + */ class Kqueue { private: std::vector<struct kevent> m_list; @@ -197,11 +211,7 @@ * This class is implemented using a bridge pattern to allow different uses * of listener implementation. * - * Currently, poll and select() are available. - * - * This wrappers takes abstract sockets as non-const reference but it does not - * own them so you must take care that sockets are still alive until the - * SocketListener is destroyed. + * Currently, poll, select and kqueue are available. */ template <typename Backend = SOCKET_DEFAULT_BACKEND> class SocketListenerBase final { @@ -209,29 +219,13 @@ static const int Read; static const int Write; - using Map = std::map<std::reference_wrapper<Socket>, int>; + using Map = std::map<Socket, int>; private: Backend m_backend; Map m_map; public: -#if 0 - /** - * Move constructor. - * - * @param other the other object - */ - SocketListener(SocketListener &&other) = default; - - /** - * Move operator. - * - * @param other the other object - * @return this - */ - SocketListener &operator=(SocketListener &&other) = default; -#endif inline SocketListenerBase() { } @@ -241,7 +235,7 @@ * * @param list the list */ - inline SocketListenerBase(std::initializer_list<std::pair<std::reference_wrapper<Socket>, int>> list) + inline SocketListenerBase(std::initializer_list<std::pair<Socket, int>> list) { for (const auto &p : list) { set(p.first, p.second); @@ -314,7 +308,7 @@ * @param sc the socket * @param flags (may be OR'ed) */ - void set(Socket &sc, int flags) + void set(Socket sc, int flags) { if (m_map.count(sc) > 0) { m_map[sc] |= flags; @@ -336,7 +330,7 @@ * @param flags the flags (may be OR'ed) * @see remove */ - void unset(Socket &sc, int flags) noexcept + void unset(Socket sc, int flags) noexcept { if (m_map.count(sc) > 0) { m_map[sc] &= ~(flags); @@ -354,7 +348,7 @@ * * @param sc the socket */ - inline void remove(Socket &sc) noexcept + inline void remove(Socket sc) noexcept { m_map.erase(sc); m_backend.remove(sc);