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);
--- a/tools/CMakeLists.txt	Wed Apr 08 12:33:45 2015 +0200
+++ b/tools/CMakeLists.txt	Tue Apr 28 07:52:45 2015 +0200
@@ -20,4 +20,4 @@
 
 add_executable(cccat cccat.cpp)
 add_executable(mdtohtml mdtohtml.cpp)
-add_subdirectory(mkunicode)
\ No newline at end of file
+#add_subdirectory(mkunicode)