/workspaces/astro/sol3-sdk/cpp/sol3/asio/handlers.h Source File

Space-ng SDK: /workspaces/astro/sol3-sdk/cpp/sol3/asio/handlers.h Source File
Space-ng SDK
handlers.h
Go to the documentation of this file.
1 // Copyright (c) Space-ng, inc. All rights reserved.
2 
3 #pragma once
4 
12 
13 #include "sol3/log/except.h"
14 
15 #include <boost/asio/bind_executor.hpp>
16 #include <boost/asio/dispatch.hpp>
17 #include <boost/asio/post.hpp>
18 
19 #include <functional>
20 #include <memory>
21 #include <tuple>
22 #include <utility>
23 
24 namespace sol3::asio {
25 namespace detail {
26 
27 template <typename TDerived, typename TClass, typename TCallable>
28 auto bind_weak(std::weak_ptr<TClass> weak_ptr, TCallable&& callable) {
30  weak_ptr.use_count() > 0,
31  "weakBind requires an initialized weak_ptr. "
32  "(Did you call weak_from_this() in a constructor?)");
33 
34  return [weak = std::move(weak_ptr),
35  cb = std::forward<TCallable>(callable)](auto&&... args) mutable {
36  if (auto base_self = weak.lock()) {
37  auto self = std::static_pointer_cast<TDerived>(std::move(base_self));
38  std::invoke(cb, std::move(self), std::forward<decltype(args)>(args)...);
39  }
40  };
41 }
42 
43 template <typename TDerived, typename TClass, typename TCallable>
44 auto bind_shared(std::shared_ptr<TClass> shared_ptr, TCallable&& callable) {
46  shared_ptr.use_count() > 0,
47  "bind requires an initialized shared_ptr. "
48  "(Did you call shared_from_this() in a constructor?)");
49 
50  return [self = std::static_pointer_cast<TDerived>(std::move(shared_ptr)),
51  cb = std::forward<TCallable>(callable)](auto&&... args) mutable {
52  std::invoke(cb, self, std::forward<decltype(args)>(args)...);
53  };
54 }
55 
58 template <typename TMemberFn, typename... TArgs>
59 auto pack_method(TMemberFn method, TArgs&&... args) {
60  return [method, args_tuple = std::make_tuple(std::forward<TArgs>(args)...)](
61  auto self, auto&&... asio_args) mutable {
62  std::apply(
63  [&](auto&&... unpacked_args) {
64  (self.get()->*method)(
65  std::forward<decltype(unpacked_args)>(unpacked_args)...,
66  std::forward<decltype(asio_args)>(asio_args)...);
67  },
68  std::move(args_tuple));
69  };
70 }
71 
72 } // namespace detail
73 
74 // =====================================================================
75 // WEAK_PTR API
76 // =====================================================================
77 
78 template <typename TClass, typename TCallable>
79 auto weakHandler(TClass* obj, TCallable&& callable) {
80  if constexpr (std::is_member_function_pointer_v<std::decay_t<TCallable>>) {
81  return detail::bind_weak<TClass>(
82  obj->weak_from_this(), detail::pack_method(callable));
83  } else {
84  return detail::bind_weak<TClass>(
85  obj->weak_from_this(), std::forward<TCallable>(callable));
86  }
87 }
88 
89 template <typename TExecutor, typename TClass, typename TFunc>
90 void weakDispatch(TExecutor const& ex, TClass* obj, TFunc&& func) {
92  ex,
93  detail::bind_weak<TClass>(
94  obj->weak_from_this(), std::forward<TFunc>(func)));
95 }
96 
97 template <
98  typename TExecutor,
99  typename TClass,
100  typename TMemberFn,
101  typename... TArgs>
103  TExecutor const& ex, TClass* obj, TMemberFn method, TArgs&&... args) {
105  ex,
106  detail::bind_weak<TClass>(
107  obj->weak_from_this(),
108  detail::pack_method(method, std::forward<TArgs>(args)...)));
109 }
110 
111 template <typename TExecutor, typename TClass, typename TFunc>
112 void weakPost(TExecutor const& ex, TClass* obj, TFunc&& func) {
114  ex,
115  detail::bind_weak<TClass>(
116  obj->weak_from_this(), std::forward<TFunc>(func)));
117 }
118 
119 template <
120  typename TExecutor,
121  typename TClass,
122  typename TMemberFn,
123  typename... TArgs>
124 void weakPost(
125  TExecutor const& ex, TClass* obj, TMemberFn method, TArgs&&... args) {
127  ex,
128  detail::bind_weak<TClass>(
129  obj->weak_from_this(),
130  detail::pack_method(method, std::forward<TArgs>(args)...)));
131 }
132 
133 template <typename TExecutor, typename TClass, typename TFunc>
134 decltype(auto) weakBindExecutor(
135  TExecutor const& ex, TClass* obj, TFunc&& func) {
136  return boost::asio::bind_executor(
137  ex,
138  detail::bind_weak<TClass>(
139  obj->weak_from_this(), std::forward<TFunc>(func)));
140 }
141 
142 template <
143  typename TExecutor,
144  typename TClass,
145  typename TMemberFn,
146  typename... TArgs>
147 decltype(auto) weakBindExecutor(
148  TExecutor const& ex, TClass* obj, TMemberFn method, TArgs&&... args) {
149  return boost::asio::bind_executor(
150  ex,
151  detail::bind_weak<TClass>(
152  obj->weak_from_this(),
153  detail::pack_method(method, std::forward<TArgs>(args)...)));
154 }
155 
156 // =====================================================================
157 // SHARED_PTR API
158 // =====================================================================
159 
160 template <typename TClass, typename TCallable>
161 auto handler(TClass* obj, TCallable&& callable) {
162  if constexpr (std::is_member_function_pointer_v<std::decay_t<TCallable>>) {
163  return detail::bind_shared<TClass>(
164  obj->shared_from_this(), detail::pack_method(callable));
165  } else {
166  return detail::bind_shared<TClass>(
167  obj->shared_from_this(), std::forward<TCallable>(callable));
168  }
169 }
170 
171 template <typename TExecutor, typename TClass, typename TFunc>
172 void dispatch(TExecutor const& ex, TClass* obj, TFunc&& func) {
174  ex,
175  detail::bind_shared<TClass>(
176  obj->shared_from_this(), std::forward<TFunc>(func)));
177 }
178 
179 template <
180  typename TExecutor,
181  typename TClass,
182  typename TMemberFn,
183  typename... TArgs>
184 void dispatch(
185  TExecutor const& ex, TClass* obj, TMemberFn method, TArgs&&... args) {
187  ex,
188  detail::bind_shared<TClass>(
189  obj->shared_from_this(),
190  detail::pack_method(method, std::forward<TArgs>(args)...)));
191 }
192 
193 template <typename TExecutor, typename TClass, typename TFunc>
194 void post(TExecutor const& ex, TClass* obj, TFunc&& func) {
196  ex,
197  detail::bind_shared<TClass>(
198  obj->shared_from_this(), std::forward<TFunc>(func)));
199 }
200 
201 template <
202  typename TExecutor,
203  typename TClass,
204  typename TMemberFn,
205  typename... TArgs>
206 void post(TExecutor const& ex, TClass* obj, TMemberFn method, TArgs&&... args) {
208  ex,
209  detail::bind_shared<TClass>(
210  obj->shared_from_this(),
211  detail::pack_method(method, std::forward<TArgs>(args)...)));
212 }
213 
214 template <typename TExecutor, typename TClass, typename TFunc>
215 decltype(auto) bindExecutor(TExecutor const& ex, TClass* obj, TFunc&& func) {
216  return boost::asio::bind_executor(
217  ex,
218  detail::bind_shared<TClass>(
219  obj->shared_from_this(), std::forward<TFunc>(func)));
220 }
221 
222 template <
223  typename TExecutor,
224  typename TClass,
225  typename TMemberFn,
226  typename... TArgs>
227 decltype(auto) bindExecutor(
228  TExecutor const& ex, TClass* obj, TMemberFn method, TArgs&&... args) {
229  return boost::asio::bind_executor(
230  ex,
231  detail::bind_shared<TClass>(
232  obj->shared_from_this(),
233  detail::pack_method(method, std::forward<TArgs>(args)...)));
234 }
235 
236 } // namespace sol3::asio
#define SOL3_EXPECT(condition,...)
Definition: except.h:222
auto pack_method(TMemberFn method, TArgs &&... args)
Packs a member function and its arguments into a standard callable that perfectly forwards ASIO compl...
Definition: handlers.h:59
auto bind_weak(std::weak_ptr< TClass > weak_ptr, TCallable &&callable)
Definition: handlers.h:28
auto bind_shared(std::shared_ptr< TClass > shared_ptr, TCallable &&callable)
Definition: handlers.h:44
Support safely capturing this in ASIO completion handlers.
Definition: handlers.h:24
void dispatch(TExecutor const &ex, TClass *obj, TFunc &&func)
Definition: handlers.h:172
void post(TExecutor const &ex, TClass *obj, TMemberFn method, TArgs &&... args)
Definition: handlers.h:206
void weakPost(TExecutor const &ex, TClass *obj, TFunc &&func)
Definition: handlers.h:112
decltype(auto) weakBindExecutor(TExecutor const &ex, TClass *obj, TFunc &&func)
Definition: handlers.h:134
void post(TExecutor const &ex, TClass *obj, TFunc &&func)
Definition: handlers.h:194
auto weakHandler(TClass *obj, TCallable &&callable)
Definition: handlers.h:79
decltype(auto) bindExecutor(TExecutor const &ex, TClass *obj, TFunc &&func)
Definition: handlers.h:215
auto handler(TClass *obj, TCallable &&callable)
Definition: handlers.h:161
void weakDispatch(TExecutor const &ex, TClass *obj, TFunc &&func)
Definition: handlers.h:90
void dispatch(TExecutor const &ex, TClass *obj, TMemberFn method, TArgs &&... args)
Definition: handlers.h:184