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_