changeset 369:f3c762579073

Socket: add more docs into SocketListener
author David Demelier <markand@malikania.fr>
date Wed, 29 Apr 2015 14:04:58 +0200
parents 6c0015524ca9
children 2c6a4f468499
files C++/modules/Socket/SocketListener.cpp C++/modules/Socket/SocketListener.h C++/tests/Socket/main.cpp
diffstat 3 files changed, 56 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- 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));
 	}
 }
 
--- 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<SocketStatus> 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 <typename Backend = SOCKET_DEFAULT_BACKEND>
 class SocketListenerBase final {
@@ -235,6 +256,9 @@
 	SocketTable m_table;
 
 public:
+	/**
+	 * Construct an empty listener.
+	 */
 	inline SocketListenerBase()
 	{
 	}
--- 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<backend::Select> 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
  * -------------------------------------------------------- */