Mercurial > code
diff C++/SocketListener.h @ 315:c9356cb38c86
Split sockets into SocketTcp and SocketUdp
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 02 Mar 2015 14:00:48 +0100 |
parents | c019f194475a |
children | 4c0af1143fc4 |
line wrap: on
line diff
--- a/C++/SocketListener.h Wed Feb 25 13:53:41 2015 +0100 +++ b/C++/SocketListener.h Mon Mar 02 14:00:48 2015 +0100 @@ -22,6 +22,8 @@ #include <chrono> #include <functional> #include <initializer_list> +#include <map> +#include <memory> #include <utility> #include <vector> @@ -29,10 +31,10 @@ #if defined(_WIN32) # if _WIN32_WINNT >= 0x0600 -# define SOCKET_LISTENER_HAVE_POLL +# define SOCKET_HAVE_POLL # endif #else -# define SOCKET_LISTENER_HAVE_POLL +# define SOCKET_HAVE_POLL #endif /** @@ -42,7 +44,7 @@ * 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 SocketMethod { +enum class SocketMethod { Select, //!< select(2) method, fallback Poll //!< poll(2), everywhere possible }; @@ -54,9 +56,70 @@ * Result of a select call, returns the first ready socket found with its * direction. */ -struct SocketStatus { - Socket socket; //!< which socket is ready - int direction; //!< the direction +class SocketStatus { +public: + Socket &socket; //!< which socket is ready + int direction; //!< the direction +}; + +/** + * @class SocketListenerInterface + * @brief Implement the polling method + */ +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; + + /** + * 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<SocketStatus> selectMultiple(int ms) = 0; }; /** @@ -64,86 +127,28 @@ * @brief Synchronous multiplexing * * Convenient wrapper around the select() system call. + * + * 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. */ class SocketListener final { public: - /** - * @brief Function for listing all sockets - */ - using MapFunc = std::function<void (Socket &, int)>; - -#if defined(SOCKET_LISTENER_HAVE_POLL) +#if defined(SOCKET_HAVE_POLL) static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll; #else static constexpr const SocketMethod PreferredMethod = SocketMethod::Select; #endif - /** - * @class Interface - * @brief Implement the polling method - */ - class Interface { - public: - /** - * Default destructor. - */ - virtual ~Interface() = default; - - /** - * List all sockets in the interface. - * - * @param func the function - */ - virtual void list(const MapFunc &func) = 0; - - /** - * Add a socket with a specified direction. - * - * @param s the socket - * @param direction the direction - */ - virtual void add(Socket s, int direction) = 0; + static const int Read; + static const int Write; - /** - * Remove a socket with a specified direction. - * - * @param s the socket - * @param direction the direction - */ - virtual void remove(const Socket &s, int direction) = 0; - - /** - * Remove all sockets. - */ - virtual void clear() = 0; - - /** - * Get the total number of sockets in the listener. - */ - virtual unsigned size() const = 0; + using Map = std::map<std::reference_wrapper<Socket>, int>; + using Iface = std::unique_ptr<SocketListenerInterface>; - /** - * 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<SocketStatus> selectMultiple(int ms) = 0; - }; - - std::unique_ptr<Interface> m_interface; +private: + Map m_map; + Iface m_interface; public: /** @@ -166,54 +171,59 @@ * * @param method the preferred method */ - SocketListener(int method = PreferredMethod); + SocketListener(SocketMethod method = PreferredMethod); + + SocketListener(std::initializer_list<std::pair<std::reference_wrapper<Socket>, int>> list); - /** - * Createa listener with some sockets. - * - * @param list the initializer list - * @param method the preferred method - */ - SocketListener(std::initializer_list<std::pair<Socket, int>> list, int method = PreferredMethod); + inline auto begin() noexcept + { + return m_map.begin(); + } - /** - * Add a socket to listen to. - * - * @param s the socket - * @param direction the direction - */ - inline void add(Socket s, int direction) + inline auto begin() const noexcept + { + return m_map.begin(); + } + + inline auto cbegin() const noexcept { - m_interface->add(std::move(s), direction); + return m_map.cbegin(); + } + + inline auto end() noexcept + { + return m_map.end(); } - /** - * Remove a socket from the list. - * - * @param s the socket - * @param direction the direction - */ - inline void remove(const Socket &s, int direction) + inline auto end() const noexcept { - m_interface->remove(s, direction); + return m_map.end(); + } + + inline auto cend() const noexcept + { + return m_map.cend(); } - /** - * Remove every sockets in the listener. - */ - inline void clear() + void set(Socket &sc, int flags); + + void unset(Socket &sc, int flags) noexcept; + + inline void remove(Socket &sc) noexcept { + m_map.erase(sc); + m_interface->remove(sc); + } + + inline void clear() noexcept + { + m_map.clear(); m_interface->clear(); } - /** - * Get the number of clients in listener. - * - * @return the total number of sockets in the listener - */ - inline unsigned size() const + unsigned size() const noexcept { - return m_interface->size(); + return m_map.size(); } /** @@ -272,17 +282,6 @@ { return m_interface->selectMultiple(timeout); } - - /** - * List every socket in the listener. - * - * @param func the function to call - */ - template <typename Func> - inline void list(Func func) - { - m_interface->list(func); - } }; #endif // !_SOCKET_LISTENER_H_