Mercurial > code
comparison 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 |
comparison
equal
deleted
inserted
replaced
257:60f71f245c5b | 258:4ad3c85ab73e |
---|---|
17 */ | 17 */ |
18 | 18 |
19 #ifndef _SOCKET_LISTENER_H_ | 19 #ifndef _SOCKET_LISTENER_H_ |
20 #define _SOCKET_LISTENER_H_ | 20 #define _SOCKET_LISTENER_H_ |
21 | 21 |
22 #include <vector> | 22 #include <chrono> |
23 #include <functional> | |
23 | 24 |
24 #include "Socket.h" | 25 #include "Socket.h" |
25 | 26 |
26 /** | 27 /** |
27 * @class SocketTimeout | 28 * @enum SocketDirection |
28 * @brief thrown when a timeout occured | 29 * @brief The SocketDirection enum |
29 */ | 30 * |
30 class SocketTimeout final : public std::exception { | 31 * Bitmask that can be set to both reading and writing. |
31 public: | 32 */ |
32 const char *what() const noexcept override; | 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 | |
33 }; | 101 }; |
34 | 102 |
35 /** | 103 /** |
36 * @class SocketListener | 104 * @class SocketListener |
37 * @brief Synchronous multiplexing | 105 * @brief Synchronous multiplexing |
38 * | 106 * |
39 * Convenient wrapper around the select() system call. | 107 * Convenient wrapper around the select() system call. |
40 */ | 108 */ |
41 class SocketListener final { | 109 class SocketListener final { |
42 private: | |
43 std::vector<Socket> m_sockets; | |
44 | |
45 public: | 110 public: |
46 /** | 111 /** |
47 * Create a socket listener with a specific number of sockets to reserve. | 112 * @brief Function for listing all sockets |
48 * | 113 */ |
49 * @param count the number of socket to reserve (default: 0) | 114 using MapFunc = std::function<void (Socket &, SocketDirection)>; |
50 */ | 115 |
51 SocketListener(int count = 0); | 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 | |
182 | |
183 public: | |
184 /** | |
185 * Create a socket listener. | |
186 * | |
187 * @param method the preferred method | |
188 */ | |
189 SocketListener(SocketMethod method = SocketMethod::Poll); | |
52 | 190 |
53 /** | 191 /** |
54 * Add a socket to listen to. | 192 * Add a socket to listen to. |
55 * | 193 * |
56 * @param s the socket | 194 * @param s the socket |
57 */ | 195 * @param direction the direction |
58 void add(Socket s); | 196 */ |
197 inline void add(Socket s, SocketDirection direction) | |
198 { | |
199 m_interface->add(std::move(s), direction); | |
200 } | |
59 | 201 |
60 /** | 202 /** |
61 * Remove a socket from the list. | 203 * Remove a socket from the list. |
62 * | 204 * |
63 * @param s the socket | 205 * @param s the socket |
64 */ | 206 * @param direction the direction |
65 void remove(const Socket &s); | 207 */ |
208 inline void remove(const Socket &s, SocketDirection direction) | |
209 { | |
210 m_interface->remove(s, direction); | |
211 } | |
66 | 212 |
67 /** | 213 /** |
68 * Remove every sockets in the listener. | 214 * Remove every sockets in the listener. |
69 */ | 215 */ |
70 void clear(); | 216 inline void clear() |
217 { | |
218 m_interface->clear(); | |
219 } | |
71 | 220 |
72 /** | 221 /** |
73 * Get the number of clients in listener. | 222 * Get the number of clients in listener. |
74 * | 223 * |
75 * @return the number of clients in the listener. | 224 * @return the total number of sockets in the listener |
76 */ | 225 */ |
77 unsigned size(); | 226 inline unsigned size() const |
78 | 227 { |
79 /** | 228 return m_interface->size(); |
80 * Wait for an event in the socket list. If both s and us are set to 0 then | 229 } |
81 * it waits indefinitely. | 230 |
82 * | 231 /** |
83 * @param s the timeout in seconds | 232 * Select a socket. Waits for a specific amount of time specified as the duration. |
84 * @param us the timeout in milliseconds | 233 * |
85 * @see take | |
86 * @return the socket ready | 234 * @return the socket ready |
87 * @throw SocketError on error | 235 * @throw SocketError on error |
88 * @throw SocketTimeout on timeout | 236 * @throw SocketTimeout on timeout |
89 */ | 237 */ |
90 Socket &select(int s = 0, int us = 0); | 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 } | |
91 }; | 268 }; |
92 | 269 |
93 #endif // !_SOCKET_LISTENER_H_ | 270 #endif // !_SOCKET_LISTENER_H_ |