Mercurial > code
annotate C++/SocketListener.h @ 258:4ad3c85ab73e
Sockets:
* set(), get() now take template to determine the size
* recv(), recvfrom() can take a template char array to determine the size
SocketListener:
* Additional preferred poll method now supported
* Support for both reading and writing polling
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 05 Oct 2014 11:00:16 +0200 |
parents | 806dbb6011c7 |
children | 46ccfbee84d9 |
rev | line source |
---|---|
170 | 1 /* |
2 * SocketListener.h -- portable select() wrapper | |
3 * | |
4 * Copyright (c) 2013, David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #ifndef _SOCKET_LISTENER_H_ | |
20 #define _SOCKET_LISTENER_H_ | |
21 | |
258 | 22 #include <chrono> |
23 #include <functional> | |
170 | 24 |
25 #include "Socket.h" | |
26 | |
27 /** | |
258 | 28 * @enum SocketDirection |
29 * @brief The SocketDirection enum | |
30 * | |
31 * Bitmask that can be set to both reading and writing. | |
170 | 32 */ |
258 | 33 enum class SocketDirection { |
34 Read = (1 << 0), //!< only for receive | |
35 Write = (1 << 1) //!< only for sending | |
36 }; | |
37 | |
38 inline SocketDirection operator&(SocketDirection x, SocketDirection y) | |
39 { | |
40 return static_cast<SocketDirection>(static_cast<int>(x) & static_cast<int>(y)); | |
41 } | |
42 | |
43 inline SocketDirection operator|(SocketDirection x, SocketDirection y) | |
44 { | |
45 return static_cast<SocketDirection>(static_cast<int>(x) | static_cast<int>(y)); | |
46 } | |
47 | |
48 inline SocketDirection operator^(SocketDirection x, SocketDirection y) | |
49 { | |
50 return static_cast<SocketDirection>(static_cast<int>(x) ^ static_cast<int>(y)); | |
51 } | |
52 | |
53 inline SocketDirection operator~(SocketDirection x) | |
54 { | |
55 return static_cast<SocketDirection>(~static_cast<int>(x)); | |
56 } | |
57 | |
58 inline SocketDirection &operator&=(SocketDirection &x, SocketDirection y) | |
59 { | |
60 x = x & y; | |
61 | |
62 return x; | |
63 } | |
64 | |
65 inline SocketDirection &operator|=(SocketDirection &x, SocketDirection y) | |
66 { | |
67 x = x | y; | |
68 | |
69 return x; | |
70 } | |
71 | |
72 inline SocketDirection &operator^=(SocketDirection &x, SocketDirection y) | |
73 { | |
74 x = x ^ y; | |
75 | |
76 return x; | |
77 } | |
78 | |
79 /** | |
80 * @enum SocketMethod | |
81 * @brief The SocketMethod enum | |
82 * | |
83 * Select the method of polling. It is only a preferred method, for example if you | |
84 * request for poll but it is not available, select will be used. | |
85 */ | |
86 enum class SocketMethod { | |
87 Select, //!< select(2) method, fallback | |
88 Poll //!< poll(2), everywhere possible | |
89 }; | |
90 | |
91 /** | |
92 * @struct SocketStatus | |
93 * @brief The SocketStatus struct | |
94 * | |
95 * Result of a select call, returns the first ready socket found with its | |
96 * direction. | |
97 */ | |
98 struct SocketStatus { | |
99 Socket socket; //!< which socket is ready | |
100 SocketDirection direction; //!< the direction | |
170 | 101 }; |
102 | |
188
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
103 /** |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
104 * @class SocketListener |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
105 * @brief Synchronous multiplexing |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
106 * |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
107 * Convenient wrapper around the select() system call. |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
108 */ |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
109 class SocketListener final { |
258 | 110 public: |
111 /** | |
112 * @brief Function for listing all sockets | |
113 */ | |
114 using MapFunc = std::function<void (Socket &, SocketDirection)>; | |
115 | |
116 /** | |
117 * @class Interface | |
118 * @brief Implement the polling method | |
119 */ | |
120 class Interface { | |
121 public: | |
122 /** | |
123 * Default destructor. | |
124 */ | |
125 virtual ~Interface() = default; | |
126 | |
127 /** | |
128 * List all sockets in the interface. | |
129 * | |
130 * @param func the function | |
131 */ | |
132 virtual void list(const MapFunc &func) = 0; | |
133 | |
134 /** | |
135 * Add a socket with a specified direction. | |
136 * | |
137 * @param s the socket | |
138 * @param direction the direction | |
139 */ | |
140 virtual void add(Socket &&s, SocketDirection direction) = 0; | |
141 | |
142 /** | |
143 * Remove a socket with a specified direction. | |
144 * | |
145 * @param s the socket | |
146 * @param direction the direction | |
147 */ | |
148 virtual void remove(const Socket &s, SocketDirection direction) = 0; | |
149 | |
150 /** | |
151 * Remove all sockets. | |
152 */ | |
153 virtual void clear() = 0; | |
154 | |
155 /** | |
156 * Get the total number of sockets in the listener. | |
157 */ | |
158 virtual unsigned size() const = 0; | |
159 | |
160 /** | |
161 * Select a socket. | |
162 * | |
163 * @param ms the number of milliseconds to wait, -1 means forever | |
164 * @return the socket status | |
165 * @throw error::Failure on failure | |
166 * @throw error::Timeout on timeout | |
167 */ | |
168 virtual SocketStatus select(int ms) = 0; | |
169 }; | |
170 | |
171 std::unique_ptr<Interface> m_interface; | |
172 | |
173 #if defined(_WIN32) | |
174 # if _WIN32_WINNT >= 0x0600 | |
175 static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll; | |
176 # else | |
177 static constexpr const SocketMethod PreferredMethod = SocketMethod::Select; | |
178 # endif | |
179 #else | |
180 static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll; | |
181 #endif | |
170 | 182 |
183 public: | |
184 /** | |
258 | 185 * Create a socket listener. |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
186 * |
258 | 187 * @param method the preferred method |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
188 */ |
258 | 189 SocketListener(SocketMethod method = SocketMethod::Poll); |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
190 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
191 /** |
170 | 192 * Add a socket to listen to. |
193 * | |
194 * @param s the socket | |
258 | 195 * @param direction the direction |
170 | 196 */ |
258 | 197 inline void add(Socket s, SocketDirection direction) |
198 { | |
199 m_interface->add(std::move(s), direction); | |
200 } | |
170 | 201 |
202 /** | |
203 * Remove a socket from the list. | |
204 * | |
205 * @param s the socket | |
258 | 206 * @param direction the direction |
170 | 207 */ |
258 | 208 inline void remove(const Socket &s, SocketDirection direction) |
209 { | |
210 m_interface->remove(s, direction); | |
211 } | |
170 | 212 |
213 /** | |
214 * Remove every sockets in the listener. | |
215 */ | |
258 | 216 inline void clear() |
217 { | |
218 m_interface->clear(); | |
219 } | |
170 | 220 |
221 /** | |
194
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
222 * Get the number of clients in listener. |
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
223 * |
258 | 224 * @return the total number of sockets in the listener |
194
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
225 */ |
258 | 226 inline unsigned size() const |
227 { | |
228 return m_interface->size(); | |
229 } | |
194
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
230 |
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
231 /** |
258 | 232 * Select a socket. Waits for a specific amount of time specified as the duration. |
170 | 233 * |
247 | 234 * @return the socket ready |
170 | 235 * @throw SocketError on error |
236 * @throw SocketTimeout on timeout | |
237 */ | |
258 | 238 template <typename Rep, typename Ratio> |
239 inline SocketStatus select(const std::chrono::duration<Rep, Ratio> &duration) | |
240 { | |
241 auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration); | |
242 | |
243 return m_interface->select(cvt.count()); | |
244 } | |
245 | |
246 /** | |
247 * Overload that waits indefinitely. | |
248 * | |
249 * @return the socket ready | |
250 * @throw SocketError on error | |
251 * @throw SocketTimeout on timeout | |
252 */ | |
253 inline SocketStatus select() | |
254 { | |
255 return m_interface->select(-1); | |
256 } | |
257 | |
258 /** | |
259 * List every socket in the listener. | |
260 * | |
261 * @param func the function to call | |
262 */ | |
263 template <typename Func> | |
264 inline void list(Func func) | |
265 { | |
266 m_interface->list(func); | |
267 } | |
170 | 268 }; |
269 | |
270 #endif // !_SOCKET_LISTENER_H_ |