diff C++/SocketListener.h @ 270:46ccfbee84d9

Socket: * Add macro SOCKET_LISTENER_HAVE_POLL to enable / disable poll(2) method if it is not available. Fallback safely to select(2) if needed. * Add new function selectMultiple() which returns a std::vector of all ready sockets. * Add tests for multiple selection.
author David Demelier <markand@malikania.fr>
date Tue, 21 Oct 2014 10:13:33 +0200
parents 4ad3c85ab73e
children f7000cc599d0
line wrap: on
line diff
--- a/C++/SocketListener.h	Fri Oct 17 14:20:00 2014 +0200
+++ b/C++/SocketListener.h	Tue Oct 21 10:13:33 2014 +0200
@@ -21,9 +21,18 @@
 
 #include <chrono>
 #include <functional>
+#include <vector>
 
 #include "Socket.h"
 
+#if defined(_WIN32)
+#  if _WIN32_WINNT >= 0x0600
+#    define SOCKET_LISTENER_HAVE_POLL
+#  endif
+#else
+#  define SOCKET_LISTENER_HAVE_POLL
+#endif
+
 /**
  * @enum SocketDirection
  * @brief The SocketDirection enum
@@ -113,6 +122,12 @@
 	 */
 	using MapFunc	= std::function<void (Socket &, SocketDirection)>;
 
+#if defined(SOCKET_LISTENER_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
@@ -158,7 +173,7 @@
 		virtual unsigned size() const = 0;
 
 		/**
-		 * Select a socket.
+		 * Select one socket.
 		 *
 		 * @param ms the number of milliseconds to wait, -1 means forever
 		 * @return the socket status
@@ -166,20 +181,20 @@
 		 * @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;
 
-#if defined(_WIN32)
-#  if _WIN32_WINNT >= 0x0600
-	static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll;
-#  else
-	static constexpr const SocketMethod PreferredMethod = SocketMethod::Select;
-#  endif
-#else
-	static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll;
-#endif
-
 public:
 	/**
 	 * Create a socket listener.
@@ -231,6 +246,7 @@
 	/**
 	 * Select a socket. Waits for a specific amount of time specified as the duration.
 	 *
+	 * @param duration the duration
 	 * @return the socket ready
 	 * @throw SocketError on error
 	 * @throw SocketTimeout on timeout
@@ -256,6 +272,34 @@
 	}
 
 	/**
+	 * Select multiple sockets.
+	 *
+	 * @param duration the duration
+	 * @return the socket ready
+	 * @throw SocketError on error
+	 * @throw SocketTimeout on timeout
+	 */
+	template <typename Rep, typename Ratio>
+	inline std::vector<SocketStatus> selectMultiple(const std::chrono::duration<Rep, Ratio> &duration)
+	{
+		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
+
+		return m_interface->selectMultiple(cvt.count());
+	}
+
+	/**
+	 * Overload that waits indefinitely.
+	 *
+	 * @return the socket ready
+	 * @throw SocketError on error
+	 * @throw SocketTimeout on timeout
+	 */
+	inline std::vector<SocketStatus> selectMultiple()
+	{
+		return m_interface->selectMultiple(-1);
+	}
+
+	/**
 	 * List every socket in the listener.
 	 *
 	 * @param func the function to call