Mercurial > code
comparison C++/SocketListener.h @ 315:c9356cb38c86
Split sockets into SocketTcp and SocketUdp
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 02 Mar 2015 14:00:48 +0100 |
parents | c019f194475a |
children | 4c0af1143fc4 |
comparison
equal
deleted
inserted
replaced
314:4c3019385769 | 315:c9356cb38c86 |
---|---|
20 #define _SOCKET_LISTENER_H_ | 20 #define _SOCKET_LISTENER_H_ |
21 | 21 |
22 #include <chrono> | 22 #include <chrono> |
23 #include <functional> | 23 #include <functional> |
24 #include <initializer_list> | 24 #include <initializer_list> |
25 #include <map> | |
26 #include <memory> | |
25 #include <utility> | 27 #include <utility> |
26 #include <vector> | 28 #include <vector> |
27 | 29 |
28 #include "Socket.h" | 30 #include "Socket.h" |
29 | 31 |
30 #if defined(_WIN32) | 32 #if defined(_WIN32) |
31 # if _WIN32_WINNT >= 0x0600 | 33 # if _WIN32_WINNT >= 0x0600 |
32 # define SOCKET_LISTENER_HAVE_POLL | 34 # define SOCKET_HAVE_POLL |
33 # endif | 35 # endif |
34 #else | 36 #else |
35 # define SOCKET_LISTENER_HAVE_POLL | 37 # define SOCKET_HAVE_POLL |
36 #endif | 38 #endif |
37 | 39 |
38 /** | 40 /** |
39 * @enum SocketMethod | 41 * @enum SocketMethod |
40 * @brief The SocketMethod enum | 42 * @brief The SocketMethod enum |
41 * | 43 * |
42 * Select the method of polling. It is only a preferred method, for example if you | 44 * Select the method of polling. It is only a preferred method, for example if you |
43 * request for poll but it is not available, select will be used. | 45 * request for poll but it is not available, select will be used. |
44 */ | 46 */ |
45 enum SocketMethod { | 47 enum class SocketMethod { |
46 Select, //!< select(2) method, fallback | 48 Select, //!< select(2) method, fallback |
47 Poll //!< poll(2), everywhere possible | 49 Poll //!< poll(2), everywhere possible |
48 }; | 50 }; |
49 | 51 |
50 /** | 52 /** |
52 * @brief The SocketStatus struct | 54 * @brief The SocketStatus struct |
53 * | 55 * |
54 * Result of a select call, returns the first ready socket found with its | 56 * Result of a select call, returns the first ready socket found with its |
55 * direction. | 57 * direction. |
56 */ | 58 */ |
57 struct SocketStatus { | 59 class SocketStatus { |
58 Socket socket; //!< which socket is ready | 60 public: |
59 int direction; //!< the direction | 61 Socket &socket; //!< which socket is ready |
62 int direction; //!< the direction | |
63 }; | |
64 | |
65 /** | |
66 * @class SocketListenerInterface | |
67 * @brief Implement the polling method | |
68 */ | |
69 class SocketListenerInterface { | |
70 public: | |
71 /** | |
72 * Default destructor. | |
73 */ | |
74 virtual ~SocketListenerInterface() = default; | |
75 | |
76 /** | |
77 * Add a socket with a specified direction. | |
78 * | |
79 * @param s the socket | |
80 * @param direction the direction | |
81 */ | |
82 virtual void set(Socket &sc, int direction) = 0; | |
83 | |
84 /** | |
85 * Remove a socket with a specified direction. | |
86 * | |
87 * @param s the socket | |
88 * @param direction the direction | |
89 */ | |
90 virtual void unset(Socket &sc, int direction) = 0; | |
91 | |
92 /** | |
93 * Remove completely a socket. | |
94 * | |
95 * @param sc the socket to remove | |
96 */ | |
97 virtual void remove(Socket &sc) = 0; | |
98 | |
99 /** | |
100 * Remove all sockets. | |
101 */ | |
102 virtual void clear() = 0; | |
103 | |
104 /** | |
105 * Select one socket. | |
106 * | |
107 * @param ms the number of milliseconds to wait, -1 means forever | |
108 * @return the socket status | |
109 * @throw error::Failure on failure | |
110 * @throw error::Timeout on timeout | |
111 */ | |
112 virtual SocketStatus select(int ms) = 0; | |
113 | |
114 /** | |
115 * Select many sockets. | |
116 * | |
117 * @param ms the number of milliseconds to wait, -1 means forever | |
118 * @return a vector of ready sockets | |
119 * @throw error::Failure on failure | |
120 * @throw error::Timeout on timeout | |
121 */ | |
122 virtual std::vector<SocketStatus> selectMultiple(int ms) = 0; | |
60 }; | 123 }; |
61 | 124 |
62 /** | 125 /** |
63 * @class SocketListener | 126 * @class SocketListener |
64 * @brief Synchronous multiplexing | 127 * @brief Synchronous multiplexing |
65 * | 128 * |
66 * Convenient wrapper around the select() system call. | 129 * Convenient wrapper around the select() system call. |
130 * | |
131 * This wrappers takes abstract sockets as non-const reference but it does not | |
132 * own them so you must take care that sockets are still alive until the | |
133 * SocketListener is destroyed. | |
67 */ | 134 */ |
68 class SocketListener final { | 135 class SocketListener final { |
69 public: | 136 public: |
70 /** | 137 #if defined(SOCKET_HAVE_POLL) |
71 * @brief Function for listing all sockets | |
72 */ | |
73 using MapFunc = std::function<void (Socket &, int)>; | |
74 | |
75 #if defined(SOCKET_LISTENER_HAVE_POLL) | |
76 static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll; | 138 static constexpr const SocketMethod PreferredMethod = SocketMethod::Poll; |
77 #else | 139 #else |
78 static constexpr const SocketMethod PreferredMethod = SocketMethod::Select; | 140 static constexpr const SocketMethod PreferredMethod = SocketMethod::Select; |
79 #endif | 141 #endif |
80 | 142 |
81 /** | 143 static const int Read; |
82 * @class Interface | 144 static const int Write; |
83 * @brief Implement the polling method | 145 |
84 */ | 146 using Map = std::map<std::reference_wrapper<Socket>, int>; |
85 class Interface { | 147 using Iface = std::unique_ptr<SocketListenerInterface>; |
86 public: | 148 |
87 /** | 149 private: |
88 * Default destructor. | 150 Map m_map; |
89 */ | 151 Iface m_interface; |
90 virtual ~Interface() = default; | |
91 | |
92 /** | |
93 * List all sockets in the interface. | |
94 * | |
95 * @param func the function | |
96 */ | |
97 virtual void list(const MapFunc &func) = 0; | |
98 | |
99 /** | |
100 * Add a socket with a specified direction. | |
101 * | |
102 * @param s the socket | |
103 * @param direction the direction | |
104 */ | |
105 virtual void add(Socket s, int direction) = 0; | |
106 | |
107 /** | |
108 * Remove a socket with a specified direction. | |
109 * | |
110 * @param s the socket | |
111 * @param direction the direction | |
112 */ | |
113 virtual void remove(const Socket &s, int direction) = 0; | |
114 | |
115 /** | |
116 * Remove all sockets. | |
117 */ | |
118 virtual void clear() = 0; | |
119 | |
120 /** | |
121 * Get the total number of sockets in the listener. | |
122 */ | |
123 virtual unsigned size() const = 0; | |
124 | |
125 /** | |
126 * Select one socket. | |
127 * | |
128 * @param ms the number of milliseconds to wait, -1 means forever | |
129 * @return the socket status | |
130 * @throw error::Failure on failure | |
131 * @throw error::Timeout on timeout | |
132 */ | |
133 virtual SocketStatus select(int ms) = 0; | |
134 | |
135 /** | |
136 * Select many sockets. | |
137 * | |
138 * @param ms the number of milliseconds to wait, -1 means forever | |
139 * @return a vector of ready sockets | |
140 * @throw error::Failure on failure | |
141 * @throw error::Timeout on timeout | |
142 */ | |
143 virtual std::vector<SocketStatus> selectMultiple(int ms) = 0; | |
144 }; | |
145 | |
146 std::unique_ptr<Interface> m_interface; | |
147 | 152 |
148 public: | 153 public: |
149 /** | 154 /** |
150 * Move constructor. | 155 * Move constructor. |
151 * | 156 * |
164 /** | 169 /** |
165 * Create a socket listener. | 170 * Create a socket listener. |
166 * | 171 * |
167 * @param method the preferred method | 172 * @param method the preferred method |
168 */ | 173 */ |
169 SocketListener(int method = PreferredMethod); | 174 SocketListener(SocketMethod method = PreferredMethod); |
170 | 175 |
171 /** | 176 SocketListener(std::initializer_list<std::pair<std::reference_wrapper<Socket>, int>> list); |
172 * Createa listener with some sockets. | 177 |
173 * | 178 inline auto begin() noexcept |
174 * @param list the initializer list | 179 { |
175 * @param method the preferred method | 180 return m_map.begin(); |
176 */ | 181 } |
177 SocketListener(std::initializer_list<std::pair<Socket, int>> list, int method = PreferredMethod); | 182 |
178 | 183 inline auto begin() const noexcept |
179 /** | 184 { |
180 * Add a socket to listen to. | 185 return m_map.begin(); |
181 * | 186 } |
182 * @param s the socket | 187 |
183 * @param direction the direction | 188 inline auto cbegin() const noexcept |
184 */ | 189 { |
185 inline void add(Socket s, int direction) | 190 return m_map.cbegin(); |
186 { | 191 } |
187 m_interface->add(std::move(s), direction); | 192 |
188 } | 193 inline auto end() noexcept |
189 | 194 { |
190 /** | 195 return m_map.end(); |
191 * Remove a socket from the list. | 196 } |
192 * | 197 |
193 * @param s the socket | 198 inline auto end() const noexcept |
194 * @param direction the direction | 199 { |
195 */ | 200 return m_map.end(); |
196 inline void remove(const Socket &s, int direction) | 201 } |
197 { | 202 |
198 m_interface->remove(s, direction); | 203 inline auto cend() const noexcept |
199 } | 204 { |
200 | 205 return m_map.cend(); |
201 /** | 206 } |
202 * Remove every sockets in the listener. | 207 |
203 */ | 208 void set(Socket &sc, int flags); |
204 inline void clear() | 209 |
205 { | 210 void unset(Socket &sc, int flags) noexcept; |
211 | |
212 inline void remove(Socket &sc) noexcept | |
213 { | |
214 m_map.erase(sc); | |
215 m_interface->remove(sc); | |
216 } | |
217 | |
218 inline void clear() noexcept | |
219 { | |
220 m_map.clear(); | |
206 m_interface->clear(); | 221 m_interface->clear(); |
207 } | 222 } |
208 | 223 |
209 /** | 224 unsigned size() const noexcept |
210 * Get the number of clients in listener. | 225 { |
211 * | 226 return m_map.size(); |
212 * @return the total number of sockets in the listener | |
213 */ | |
214 inline unsigned size() const | |
215 { | |
216 return m_interface->size(); | |
217 } | 227 } |
218 | 228 |
219 /** | 229 /** |
220 * Select a socket. Waits for a specific amount of time specified as the duration. | 230 * Select a socket. Waits for a specific amount of time specified as the duration. |
221 * | 231 * |
270 */ | 280 */ |
271 inline std::vector<SocketStatus> selectMultiple(int timeout = -1) | 281 inline std::vector<SocketStatus> selectMultiple(int timeout = -1) |
272 { | 282 { |
273 return m_interface->selectMultiple(timeout); | 283 return m_interface->selectMultiple(timeout); |
274 } | 284 } |
275 | |
276 /** | |
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 } | |
286 }; | 285 }; |
287 | 286 |
288 #endif // !_SOCKET_LISTENER_H_ | 287 #endif // !_SOCKET_LISTENER_H_ |