1//
2// bind_immediate_executor.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
12#define BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19#include <boost/asio/detail/type_traits.hpp>
20#include <boost/asio/associated_immediate_executor.hpp>
21#include <boost/asio/associator.hpp>
22#include <boost/asio/async_result.hpp>
23
24#include <boost/asio/detail/push_options.hpp>
25
26namespace boost {
27namespace asio {
28namespace detail {
29
30// Helper to automatically define nested typedef result_type.
31
32template <typename T, typename = void>
33struct immediate_executor_binder_result_type
34{
35protected:
36 typedef void result_type_or_void;
37};
38
39template <typename T>
40struct immediate_executor_binder_result_type<T, void_t<typename T::result_type>>
41{
42 typedef typename T::result_type result_type;
43protected:
44 typedef result_type result_type_or_void;
45};
46
47template <typename R>
48struct immediate_executor_binder_result_type<R(*)()>
49{
50 typedef R result_type;
51protected:
52 typedef result_type result_type_or_void;
53};
54
55template <typename R>
56struct immediate_executor_binder_result_type<R(&)()>
57{
58 typedef R result_type;
59protected:
60 typedef result_type result_type_or_void;
61};
62
63template <typename R, typename A1>
64struct immediate_executor_binder_result_type<R(*)(A1)>
65{
66 typedef R result_type;
67protected:
68 typedef result_type result_type_or_void;
69};
70
71template <typename R, typename A1>
72struct immediate_executor_binder_result_type<R(&)(A1)>
73{
74 typedef R result_type;
75protected:
76 typedef result_type result_type_or_void;
77};
78
79template <typename R, typename A1, typename A2>
80struct immediate_executor_binder_result_type<R(*)(A1, A2)>
81{
82 typedef R result_type;
83protected:
84 typedef result_type result_type_or_void;
85};
86
87template <typename R, typename A1, typename A2>
88struct immediate_executor_binder_result_type<R(&)(A1, A2)>
89{
90 typedef R result_type;
91protected:
92 typedef result_type result_type_or_void;
93};
94
95// Helper to automatically define nested typedef argument_type.
96
97template <typename T, typename = void>
98struct immediate_executor_binder_argument_type {};
99
100template <typename T>
101struct immediate_executor_binder_argument_type<T,
102 void_t<typename T::argument_type>>
103{
104 typedef typename T::argument_type argument_type;
105};
106
107template <typename R, typename A1>
108struct immediate_executor_binder_argument_type<R(*)(A1)>
109{
110 typedef A1 argument_type;
111};
112
113template <typename R, typename A1>
114struct immediate_executor_binder_argument_type<R(&)(A1)>
115{
116 typedef A1 argument_type;
117};
118
119// Helper to automatically define nested typedefs first_argument_type and
120// second_argument_type.
121
122template <typename T, typename = void>
123struct immediate_executor_binder_argument_types {};
124
125template <typename T>
126struct immediate_executor_binder_argument_types<T,
127 void_t<typename T::first_argument_type>>
128{
129 typedef typename T::first_argument_type first_argument_type;
130 typedef typename T::second_argument_type second_argument_type;
131};
132
133template <typename R, typename A1, typename A2>
134struct immediate_executor_binder_argument_type<R(*)(A1, A2)>
135{
136 typedef A1 first_argument_type;
137 typedef A2 second_argument_type;
138};
139
140template <typename R, typename A1, typename A2>
141struct immediate_executor_binder_argument_type<R(&)(A1, A2)>
142{
143 typedef A1 first_argument_type;
144 typedef A2 second_argument_type;
145};
146
147} // namespace detail
148
149/// A call wrapper type to bind a immediate executor of type @c Executor
150/// to an object of type @c T.
151template <typename T, typename Executor>
152class immediate_executor_binder
153#if !defined(GENERATING_DOCUMENTATION)
154 : public detail::immediate_executor_binder_result_type<T>,
155 public detail::immediate_executor_binder_argument_type<T>,
156 public detail::immediate_executor_binder_argument_types<T>
157#endif // !defined(GENERATING_DOCUMENTATION)
158{
159public:
160 /// The type of the target object.
161 typedef T target_type;
162
163 /// The type of the associated immediate executor.
164 typedef Executor immediate_executor_type;
165
166#if defined(GENERATING_DOCUMENTATION)
167 /// The return type if a function.
168 /**
169 * The type of @c result_type is based on the type @c T of the wrapper's
170 * target object:
171 *
172 * @li if @c T is a pointer to function type, @c result_type is a synonym for
173 * the return type of @c T;
174 *
175 * @li if @c T is a class type with a member type @c result_type, then @c
176 * result_type is a synonym for @c T::result_type;
177 *
178 * @li otherwise @c result_type is not defined.
179 */
180 typedef see_below result_type;
181
182 /// The type of the function's argument.
183 /**
184 * The type of @c argument_type is based on the type @c T of the wrapper's
185 * target object:
186 *
187 * @li if @c T is a pointer to a function type accepting a single argument,
188 * @c argument_type is a synonym for the return type of @c T;
189 *
190 * @li if @c T is a class type with a member type @c argument_type, then @c
191 * argument_type is a synonym for @c T::argument_type;
192 *
193 * @li otherwise @c argument_type is not defined.
194 */
195 typedef see_below argument_type;
196
197 /// The type of the function's first argument.
198 /**
199 * The type of @c first_argument_type is based on the type @c T of the
200 * wrapper's target object:
201 *
202 * @li if @c T is a pointer to a function type accepting two arguments, @c
203 * first_argument_type is a synonym for the return type of @c T;
204 *
205 * @li if @c T is a class type with a member type @c first_argument_type,
206 * then @c first_argument_type is a synonym for @c T::first_argument_type;
207 *
208 * @li otherwise @c first_argument_type is not defined.
209 */
210 typedef see_below first_argument_type;
211
212 /// The type of the function's second argument.
213 /**
214 * The type of @c second_argument_type is based on the type @c T of the
215 * wrapper's target object:
216 *
217 * @li if @c T is a pointer to a function type accepting two arguments, @c
218 * second_argument_type is a synonym for the return type of @c T;
219 *
220 * @li if @c T is a class type with a member type @c first_argument_type,
221 * then @c second_argument_type is a synonym for @c T::second_argument_type;
222 *
223 * @li otherwise @c second_argument_type is not defined.
224 */
225 typedef see_below second_argument_type;
226#endif // defined(GENERATING_DOCUMENTATION)
227
228 /// Construct a immediate executor wrapper for the specified object.
229 /**
230 * This constructor is only valid if the type @c T is constructible from type
231 * @c U.
232 */
233 template <typename U>
234 immediate_executor_binder(const immediate_executor_type& e,
235 U&& u)
236 : executor_(e),
237 target_(static_cast<U&&>(u))
238 {
239 }
240
241 /// Copy constructor.
242 immediate_executor_binder(const immediate_executor_binder& other)
243 : executor_(other.get_immediate_executor()),
244 target_(other.get())
245 {
246 }
247
248 /// Construct a copy, but specify a different immediate executor.
249 immediate_executor_binder(const immediate_executor_type& e,
250 const immediate_executor_binder& other)
251 : executor_(e),
252 target_(other.get())
253 {
254 }
255
256 /// Construct a copy of a different immediate executor wrapper type.
257 /**
258 * This constructor is only valid if the @c Executor type is
259 * constructible from type @c OtherExecutor, and the type @c T is
260 * constructible from type @c U.
261 */
262 template <typename U, typename OtherExecutor>
263 immediate_executor_binder(
264 const immediate_executor_binder<U, OtherExecutor>& other,
265 constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0,
266 constraint_t<is_constructible<T, U>::value> = 0)
267 : executor_(other.get_immediate_executor()),
268 target_(other.get())
269 {
270 }
271
272 /// Construct a copy of a different immediate executor wrapper type, but
273 /// specify a different immediate executor.
274 /**
275 * This constructor is only valid if the type @c T is constructible from type
276 * @c U.
277 */
278 template <typename U, typename OtherExecutor>
279 immediate_executor_binder(const immediate_executor_type& e,
280 const immediate_executor_binder<U, OtherExecutor>& other,
281 constraint_t<is_constructible<T, U>::value> = 0)
282 : executor_(e),
283 target_(other.get())
284 {
285 }
286
287 /// Move constructor.
288 immediate_executor_binder(immediate_executor_binder&& other)
289 : executor_(static_cast<immediate_executor_type&&>(
290 other.get_immediate_executor())),
291 target_(static_cast<T&&>(other.get()))
292 {
293 }
294
295 /// Move construct the target object, but specify a different immediate
296 /// executor.
297 immediate_executor_binder(const immediate_executor_type& e,
298 immediate_executor_binder&& other)
299 : executor_(e),
300 target_(static_cast<T&&>(other.get()))
301 {
302 }
303
304 /// Move construct from a different immediate executor wrapper type.
305 template <typename U, typename OtherExecutor>
306 immediate_executor_binder(
307 immediate_executor_binder<U, OtherExecutor>&& other,
308 constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0,
309 constraint_t<is_constructible<T, U>::value> = 0)
310 : executor_(static_cast<OtherExecutor&&>(
311 other.get_immediate_executor())),
312 target_(static_cast<U&&>(other.get()))
313 {
314 }
315
316 /// Move construct from a different immediate executor wrapper type, but
317 /// specify a different immediate executor.
318 template <typename U, typename OtherExecutor>
319 immediate_executor_binder(const immediate_executor_type& e,
320 immediate_executor_binder<U, OtherExecutor>&& other,
321 constraint_t<is_constructible<T, U>::value> = 0)
322 : executor_(e),
323 target_(static_cast<U&&>(other.get()))
324 {
325 }
326
327 /// Destructor.
328 ~immediate_executor_binder()
329 {
330 }
331
332 /// Obtain a reference to the target object.
333 target_type& get() noexcept
334 {
335 return target_;
336 }
337
338 /// Obtain a reference to the target object.
339 const target_type& get() const noexcept
340 {
341 return target_;
342 }
343
344 /// Obtain the associated immediate executor.
345 immediate_executor_type get_immediate_executor() const noexcept
346 {
347 return executor_;
348 }
349
350 /// Forwarding function call operator.
351 template <typename... Args>
352 result_of_t<T(Args...)> operator()(Args&&... args)
353 {
354 return target_(static_cast<Args&&>(args)...);
355 }
356
357 /// Forwarding function call operator.
358 template <typename... Args>
359 result_of_t<T(Args...)> operator()(Args&&... args) const
360 {
361 return target_(static_cast<Args&&>(args)...);
362 }
363
364private:
365 Executor executor_;
366 T target_;
367};
368
369/// Associate an object of type @c T with a immediate executor of type
370/// @c Executor.
371template <typename Executor, typename T>
372BOOST_ASIO_NODISCARD inline immediate_executor_binder<decay_t<T>, Executor>
373bind_immediate_executor(const Executor& e, T&& t)
374{
375 return immediate_executor_binder<
376 decay_t<T>, Executor>(
377 e, static_cast<T&&>(t));
378}
379
380#if !defined(GENERATING_DOCUMENTATION)
381
382namespace detail {
383
384template <typename TargetAsyncResult, typename Executor, typename = void>
385class immediate_executor_binder_completion_handler_async_result
386{
387public:
388 template <typename T>
389 explicit immediate_executor_binder_completion_handler_async_result(T&)
390 {
391 }
392};
393
394template <typename TargetAsyncResult, typename Executor>
395class immediate_executor_binder_completion_handler_async_result<
396 TargetAsyncResult, Executor,
397 void_t<
398 typename TargetAsyncResult::completion_handler_type
399 >>
400{
401private:
402 TargetAsyncResult target_;
403
404public:
405 typedef immediate_executor_binder<
406 typename TargetAsyncResult::completion_handler_type, Executor>
407 completion_handler_type;
408
409 explicit immediate_executor_binder_completion_handler_async_result(
410 typename TargetAsyncResult::completion_handler_type& handler)
411 : target_(handler)
412 {
413 }
414
415 auto get() -> decltype(target_.get())
416 {
417 return target_.get();
418 }
419};
420
421template <typename TargetAsyncResult, typename = void>
422struct immediate_executor_binder_async_result_return_type
423{
424};
425
426template <typename TargetAsyncResult>
427struct immediate_executor_binder_async_result_return_type<
428 TargetAsyncResult,
429 void_t<
430 typename TargetAsyncResult::return_type
431 >>
432{
433 typedef typename TargetAsyncResult::return_type return_type;
434};
435
436} // namespace detail
437
438template <typename T, typename Executor, typename Signature>
439class async_result<immediate_executor_binder<T, Executor>, Signature> :
440 public detail::immediate_executor_binder_completion_handler_async_result<
441 async_result<T, Signature>, Executor>,
442 public detail::immediate_executor_binder_async_result_return_type<
443 async_result<T, Signature>>
444{
445public:
446 explicit async_result(immediate_executor_binder<T, Executor>& b)
447 : detail::immediate_executor_binder_completion_handler_async_result<
448 async_result<T, Signature>, Executor>(b.get())
449 {
450 }
451
452 template <typename Initiation>
453 struct init_wrapper
454 {
455 template <typename Init>
456 init_wrapper(const Executor& e, Init&& init)
457 : executor_(e),
458 initiation_(static_cast<Init&&>(init))
459 {
460 }
461
462 template <typename Handler, typename... Args>
463 void operator()(Handler&& handler, Args&&... args)
464 {
465 static_cast<Initiation&&>(initiation_)(
466 immediate_executor_binder<
467 decay_t<Handler>, Executor>(
468 executor_, static_cast<Handler&&>(handler)),
469 static_cast<Args&&>(args)...);
470 }
471
472 template <typename Handler, typename... Args>
473 void operator()(Handler&& handler, Args&&... args) const
474 {
475 initiation_(
476 immediate_executor_binder<
477 decay_t<Handler>, Executor>(
478 executor_, static_cast<Handler&&>(handler)),
479 static_cast<Args&&>(args)...);
480 }
481
482 Executor executor_;
483 Initiation initiation_;
484 };
485
486 template <typename Initiation, typename RawCompletionToken, typename... Args>
487 static auto initiate(Initiation&& initiation,
488 RawCompletionToken&& token, Args&&... args)
489 -> decltype(
490 async_initiate<T, Signature>(
491 declval<init_wrapper<decay_t<Initiation>>>(),
492 token.get(), static_cast<Args&&>(args)...))
493 {
494 return async_initiate<T, Signature>(
495 init_wrapper<decay_t<Initiation>>(
496 token.get_immediate_executor(),
497 static_cast<Initiation&&>(initiation)),
498 token.get(), static_cast<Args&&>(args)...);
499 }
500
501private:
502 async_result(const async_result&) = delete;
503 async_result& operator=(const async_result&) = delete;
504
505 async_result<T, Signature> target_;
506};
507
508template <template <typename, typename> class Associator,
509 typename T, typename Executor, typename DefaultCandidate>
510struct associator<Associator,
511 immediate_executor_binder<T, Executor>,
512 DefaultCandidate>
513 : Associator<T, DefaultCandidate>
514{
515 static typename Associator<T, DefaultCandidate>::type get(
516 const immediate_executor_binder<T, Executor>& b) noexcept
517 {
518 return Associator<T, DefaultCandidate>::get(b.get());
519 }
520
521 static auto get(const immediate_executor_binder<T, Executor>& b,
522 const DefaultCandidate& c) noexcept
523 -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
524 {
525 return Associator<T, DefaultCandidate>::get(b.get(), c);
526 }
527};
528
529template <typename T, typename Executor, typename Executor1>
530struct associated_immediate_executor<
531 immediate_executor_binder<T, Executor>,
532 Executor1>
533{
534 typedef Executor type;
535
536 static auto get(const immediate_executor_binder<T, Executor>& b,
537 const Executor1& = Executor1()) noexcept
538 -> decltype(b.get_immediate_executor())
539 {
540 return b.get_immediate_executor();
541 }
542};
543
544#endif // !defined(GENERATING_DOCUMENTATION)
545
546} // namespace asio
547} // namespace boost
548
549#include <boost/asio/detail/pop_options.hpp>
550
551#endif // BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
552

source code of boost/libs/asio/include/boost/asio/bind_immediate_executor.hpp