Mercurial > code
annotate C++/SocketListener.h @ 277:b544a599e08e
Socket: remove enum class
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 23 Oct 2014 17:59:14 +0200 |
parents | f7000cc599d0 |
children | adcae2bde2f0 |
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> | |
270 | 24 #include <vector> |
170 | 25 |
26 #include "Socket.h" | |
27 | |
270 | 28 #if defined(_WIN32) |
29 # if _WIN32_WINNT >= 0x0600 | |
30 # define SOCKET_LISTENER_HAVE_POLL | |
31 # endif | |
32 #else | |
33 # define SOCKET_LISTENER_HAVE_POLL | |
34 #endif | |
35 | |
170 | 36 /** |
258 | 37 * @enum SocketDirection |
38 * @brief The SocketDirection enum | |
39 * | |
40 * Bitmask that can be set to both reading and writing. | |
170 | 41 */ |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
42 enum SocketDirection { |
258 | 43 Read = (1 << 0), //!< only for receive |
44 Write = (1 << 1) //!< only for sending | |
45 }; | |
46 | |
47 /** | |
48 * @enum SocketMethod | |
49 * @brief The SocketMethod enum | |
50 * | |
51 * Select the method of polling. It is only a preferred method, for example if you | |
52 * request for poll but it is not available, select will be used. | |
53 */ | |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
54 enum SocketMethod { |
258 | 55 Select, //!< select(2) method, fallback |
56 Poll //!< poll(2), everywhere possible | |
57 }; | |
58 | |
59 /** | |
60 * @struct SocketStatus | |
61 * @brief The SocketStatus struct | |
62 * | |
63 * Result of a select call, returns the first ready socket found with its | |
64 * direction. | |
65 */ | |
66 struct SocketStatus { | |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
67 Socket socket; //!< which socket is ready |
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
68 int direction; //!< the direction |
170 | 69 }; |
70 | |
188
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
71 /** |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
72 * @class SocketListener |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
73 * @brief Synchronous multiplexing |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
74 * |
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
75 * 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
|
76 */ |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
77 class SocketListener final { |
258 | 78 public: |
79 /** | |
80 * @brief Function for listing all sockets | |
81 */ | |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
82 using MapFunc = std::function<void (Socket &, int)>; |
258 | 83 |
270 | 84 #if defined(SOCKET_LISTENER_HAVE_POLL) |
85 static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll; | |
86 #else | |
87 static constexpr const SocketMethod PreferredMethod = SocketMethod::Select; | |
88 #endif | |
89 | |
258 | 90 /** |
91 * @class Interface | |
92 * @brief Implement the polling method | |
93 */ | |
94 class Interface { | |
95 public: | |
96 /** | |
97 * Default destructor. | |
98 */ | |
99 virtual ~Interface() = default; | |
100 | |
101 /** | |
102 * List all sockets in the interface. | |
103 * | |
104 * @param func the function | |
105 */ | |
106 virtual void list(const MapFunc &func) = 0; | |
107 | |
108 /** | |
109 * Add a socket with a specified direction. | |
110 * | |
111 * @param s the socket | |
112 * @param direction the direction | |
113 */ | |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
114 virtual void add(Socket s, int direction) = 0; |
258 | 115 |
116 /** | |
117 * Remove a socket with a specified direction. | |
118 * | |
119 * @param s the socket | |
120 * @param direction the direction | |
121 */ | |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
122 virtual void remove(const Socket &s, int direction) = 0; |
258 | 123 |
124 /** | |
125 * Remove all sockets. | |
126 */ | |
127 virtual void clear() = 0; | |
128 | |
129 /** | |
130 * Get the total number of sockets in the listener. | |
131 */ | |
132 virtual unsigned size() const = 0; | |
133 | |
134 /** | |
270 | 135 * Select one socket. |
258 | 136 * |
137 * @param ms the number of milliseconds to wait, -1 means forever | |
138 * @return the socket status | |
139 * @throw error::Failure on failure | |
140 * @throw error::Timeout on timeout | |
141 */ | |
142 virtual SocketStatus select(int ms) = 0; | |
270 | 143 |
144 /** | |
145 * Select many sockets. | |
146 * | |
147 * @param ms the number of milliseconds to wait, -1 means forever | |
148 * @return a vector of ready sockets | |
149 * @throw error::Failure on failure | |
150 * @throw error::Timeout on timeout | |
151 */ | |
152 virtual std::vector<SocketStatus> selectMultiple(int ms) = 0; | |
258 | 153 }; |
154 | |
155 std::unique_ptr<Interface> m_interface; | |
156 | |
170 | 157 public: |
158 /** | |
271
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
159 * Move constructor. |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
160 * |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
161 * @param other the other object |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
162 */ |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
163 SocketListener(SocketListener &&other) = default; |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
164 |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
165 /** |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
166 * Move operator. |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
167 * |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
168 * @param other the other object |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
169 * @return this |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
170 */ |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
171 SocketListener &operator=(SocketListener &&other) = default; |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
172 |
f7000cc599d0
Socket: make listener movable
David Demelier <markand@malikania.fr>
parents:
270
diff
changeset
|
173 /** |
258 | 174 * Create a socket listener. |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
175 * |
258 | 176 * @param method the preferred method |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
177 */ |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
178 SocketListener(int method = Poll); |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
179 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
194
diff
changeset
|
180 /** |
170 | 181 * Add a socket to listen to. |
182 * | |
183 * @param s the socket | |
258 | 184 * @param direction the direction |
170 | 185 */ |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
186 inline void add(Socket s, int direction) |
258 | 187 { |
188 m_interface->add(std::move(s), direction); | |
189 } | |
170 | 190 |
191 /** | |
192 * Remove a socket from the list. | |
193 * | |
194 * @param s the socket | |
258 | 195 * @param direction the direction |
170 | 196 */ |
277
b544a599e08e
Socket: remove enum class
David Demelier <markand@malikania.fr>
parents:
271
diff
changeset
|
197 inline void remove(const Socket &s, int direction) |
258 | 198 { |
199 m_interface->remove(s, direction); | |
200 } | |
170 | 201 |
202 /** | |
203 * Remove every sockets in the listener. | |
204 */ | |
258 | 205 inline void clear() |
206 { | |
207 m_interface->clear(); | |
208 } | |
170 | 209 |
210 /** | |
194
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
211 * Get the number of clients in listener. |
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
212 * |
258 | 213 * @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
|
214 */ |
258 | 215 inline unsigned size() const |
216 { | |
217 return m_interface->size(); | |
218 } | |
194
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
219 |
9fc5f917872b
Update Luae bits and LuaSocket
David Demelier <markand@malikania.fr>
parents:
188
diff
changeset
|
220 /** |
258 | 221 * Select a socket. Waits for a specific amount of time specified as the duration. |
170 | 222 * |
270 | 223 * @param duration the duration |
247 | 224 * @return the socket ready |
170 | 225 * @throw SocketError on error |
226 * @throw SocketTimeout on timeout | |
227 */ | |
258 | 228 template <typename Rep, typename Ratio> |
229 inline SocketStatus select(const std::chrono::duration<Rep, Ratio> &duration) | |
230 { | |
231 auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration); | |
232 | |
233 return m_interface->select(cvt.count()); | |
234 } | |
235 | |
236 /** | |
237 * Overload that waits indefinitely. | |
238 * | |
239 * @return the socket ready | |
240 * @throw SocketError on error | |
241 * @throw SocketTimeout on timeout | |
242 */ | |
243 inline SocketStatus select() | |
244 { | |
245 return m_interface->select(-1); | |
246 } | |
247 | |
248 /** | |
270 | 249 * Select multiple sockets. |
250 * | |
251 * @param duration the duration | |
252 * @return the socket ready | |
253 * @throw SocketError on error | |
254 * @throw SocketTimeout on timeout | |
255 */ | |
256 template <typename Rep, typename Ratio> | |
257 inline std::vector<SocketStatus> selectMultiple(const std::chrono::duration<Rep, Ratio> &duration) | |
258 { | |
259 auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration); | |
260 | |
261 return m_interface->selectMultiple(cvt.count()); | |
262 } | |
263 | |
264 /** | |
265 * Overload that waits indefinitely. | |
266 * | |
267 * @return the socket ready | |
268 * @throw SocketError on error | |
269 * @throw SocketTimeout on timeout | |
270 */ | |
271 inline std::vector<SocketStatus> selectMultiple() | |
272 { | |
273 return m_interface->selectMultiple(-1); | |
274 } | |
275 | |
276 /** | |
258 | 277 * List every socket in the listener. |
278 * | |
279 * @param func the function to call | |
280 */ | |
281 template <typename Func> | |
282 inline void list(Func func) | |
283 { | |
284 m_interface->list(func); | |
285 } | |
170 | 286 }; |
287 | |
288 #endif // !_SOCKET_LISTENER_H_ |