libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
socket_service.hpp
1 #pragma once
2 
3 #include "fly/net/socket/concepts.hpp"
4 #include "fly/net/socket/types.hpp"
5 
6 #include <functional>
7 #include <memory>
8 #include <vector>
9 
10 namespace fly::task {
11 class SequencedTaskRunner;
12 } // namespace fly::task
13 
14 namespace fly::net {
15 
16 class NetworkConfig;
17 
25 class SocketService : public std::enable_shared_from_this<SocketService>
26 {
27 public:
31  ~SocketService() noexcept;
32 
41  static std::shared_ptr<SocketService> create(
42  std::shared_ptr<fly::task::SequencedTaskRunner> task_runner,
43  std::shared_ptr<NetworkConfig> config);
44 
50  template <Socket SocketType>
51  std::shared_ptr<SocketType> create_socket();
52 
60  void remove_socket(socket_type handle);
61 
80  template <Socket SocketType, SocketNotification<SocketType> Callback>
81  void notify_when_writable(const std::shared_ptr<SocketType> &socket, Callback &&callback);
82 
101  template <Socket SocketType, SocketNotification<SocketType> Callback>
102  void notify_when_readable(const std::shared_ptr<SocketType> &socket, Callback &&callback);
103 
104 private:
105  using Notification = std::function<void()>;
106 
107  struct Request
108  {
109  Request(socket_type handle, Notification callback) noexcept;
110 
111  socket_type m_handle;
112  Notification m_callback;
113  };
114 
121  std::shared_ptr<fly::task::SequencedTaskRunner> task_runner,
122  std::shared_ptr<NetworkConfig> config) noexcept;
123 
134  void notify_when_writable(socket_type handle, Notification &&callback);
135 
146  void notify_when_readable(socket_type handle, Notification &&callback);
147 
161  template <Socket SocketType, SocketNotification<SocketType> Callback>
162  Notification wrap_callback(const std::shared_ptr<SocketType> &socket, Callback &&callback);
163 
168  void poll();
169 
170  std::shared_ptr<fly::task::SequencedTaskRunner> m_task_runner;
171 
172  std::shared_ptr<NetworkConfig> m_config;
173 
174  std::vector<Request> m_write_requests;
175  std::vector<Request> m_read_requests;
176 };
177 
178 //==================================================================================================
179 template <Socket SocketType>
180 std::shared_ptr<SocketType> SocketService::create_socket()
181 {
182  return SocketType::create_socket(shared_from_this(), m_config);
183 }
184 
185 //==================================================================================================
186 template <Socket SocketType, SocketNotification<SocketType> Callback>
188  const std::shared_ptr<SocketType> &socket,
189  Callback &&callback)
190 {
191  notify_when_writable(socket->handle(), wrap_callback(socket, std::forward<Callback>(callback)));
192 }
193 
194 //==================================================================================================
195 template <Socket SocketType, SocketNotification<SocketType> Callback>
197  const std::shared_ptr<SocketType> &socket,
198  Callback &&callback)
199 {
200  notify_when_readable(socket->handle(), wrap_callback(socket, std::forward<Callback>(callback)));
201 }
202 
203 //==================================================================================================
204 template <Socket SocketType, SocketNotification<SocketType> Callback>
205 auto SocketService::wrap_callback(const std::shared_ptr<SocketType> &socket, Callback &&callback)
206  -> Notification
207 {
208  // Further wrap the callback in a structure to allow perfect forwarding into the lambda below.
209  struct CallbackHolder
210  {
211  Callback m_callback;
212  };
213 
214  std::weak_ptr<SocketType> weak_socket = socket;
215  CallbackHolder holder {std::forward<Callback>(callback)};
216 
217  return [weak_socket = std::move(weak_socket), holder = std::move(holder)]() mutable {
218  if (std::shared_ptr<SocketType> strong_socket = weak_socket.lock(); strong_socket)
219  {
220  std::invoke(std::move(holder.m_callback), std::move(strong_socket));
221  }
222  };
223 }
224 
225 } // namespace fly::net
Definition: socket_service.hpp:26
void notify_when_readable(const std::shared_ptr< SocketType > &socket, Callback &&callback)
Definition: socket_service.hpp:196
void remove_socket(socket_type handle)
Definition: socket_service.cpp:48
~SocketService() noexcept
Definition: socket_service.cpp:42
std::shared_ptr< SocketType > create_socket()
Definition: socket_service.hpp:180
void notify_when_writable(const std::shared_ptr< SocketType > &socket, Callback &&callback)
Definition: socket_service.hpp:187
static std::shared_ptr< SocketService > create(std::shared_ptr< fly::task::SequencedTaskRunner > task_runner, std::shared_ptr< NetworkConfig > config)
Definition: socket_service.cpp:12