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_