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_