|
1 | | -// |
2 | 1 | // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com) |
3 | 2 | // |
4 | 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
|
7 | 6 | // Official repository: https://github.com/cppalliance/capy |
8 | 7 | // |
9 | 8 |
|
10 | | -#ifndef BOOST_CAPY_ASIO_AS_IO_AWAITABLE |
11 | | -#define BOOST_CAPY_ASIO_AS_IO_AWAITABLE |
12 | | - |
13 | | -#include <boost/capy/asio/detail/as_io_awaitable.hpp> |
14 | | -#include <boost/capy/asio/detail/completion_handler.hpp> |
15 | | -#include <boost/asio/async_result.hpp> |
| 9 | +#ifndef BOOST_CAPY_ASIO_DETAIL_AS_IO_AWAITABLE_HPP |
| 10 | +#define BOOST_CAPY_ASIO_DETAIL_AS_IO_AWAITABLE_HPP |
16 | 11 |
|
17 | | -#include <optional> |
| 12 | +#include <type_traits> |
| 13 | +#include <utility> |
18 | 14 |
|
19 | | - |
20 | | -template <typename... Ts> |
21 | | -struct boost::asio::async_result<boost::capy::as_io_awaitable_t, void(Ts...)> |
| 15 | +namespace boost::capy |
22 | 16 | { |
23 | | - template<typename Initiation, typename... Args> |
24 | | - struct awaitable_t |
25 | | - { |
26 | | - cancellation_signal signal; |
27 | | - capy::detail::asio_immediate_executor_helper::completed_immediately_t ci; |
28 | 17 |
|
29 | | - struct cb |
30 | | - { |
31 | | - cancellation_signal &signal; |
32 | | - cb(cancellation_signal &signal) : signal(signal) {} |
33 | | - void operator()() {signal.emit(cancellation_type::terminal); } |
34 | | - }; |
35 | | - std::optional<std::stop_callback<cb>> stopper; |
36 | | - |
37 | | - bool await_ready() const {return false;} |
38 | 18 |
|
39 | | - void await_suspend(std::coroutine_handle<> h, const capy::io_env * env) |
40 | | - { |
41 | | - stopper.emplace(env->stop_token, signal); |
42 | | - capy::detail::asio_coroutine_completion_handler<Ts...> ch( |
43 | | - h, result_, env, |
44 | | - signal.slot(), |
45 | | - &ci); |
46 | | - |
47 | | - std::apply( |
48 | | - [&](auto ... args) |
49 | | - { |
50 | | - std::move(init_)( |
51 | | - std::move(ch), |
52 | | - std::move(args)...); |
53 | | - }, |
54 | | - std::move(args_)); |
55 | | - |
56 | | - } |
57 | | - |
58 | | - std::tuple<Ts...> await_resume() {return std::move(*result_); } |
| 19 | +struct as_io_awaitable_t |
| 20 | +{ |
| 21 | + /// Default constructor. |
| 22 | + constexpr as_io_awaitable_t() |
| 23 | + { |
| 24 | + } |
59 | 25 |
|
| 26 | + /// Adapts an executor to add the @c use_op_t completion token as the |
| 27 | + /// default. |
| 28 | + template <typename InnerExecutor> |
| 29 | + struct executor_with_default : InnerExecutor |
| 30 | + { |
| 31 | + /// Specify @c use_op_t as the default completion token type. |
| 32 | + typedef as_io_awaitable_t default_completion_token_type; |
60 | 33 |
|
61 | | - awaitable_t(Initiation init, std::tuple<Args...> args) |
62 | | - : init_(std::move(init)), args_(std::move(args)) {} |
63 | | - awaitable_t(awaitable_t && rhs) noexcept |
64 | | - : init_(std::move(rhs.init_)), args_(std::move(rhs.args_)), result_(std::move(rhs.result_)) {} |
65 | | - private: |
66 | | - Initiation init_; |
67 | | - std::tuple<Args...> args_; |
68 | | - std::optional<std::tuple<Ts...>> result_; |
69 | | - |
70 | | - }; |
| 34 | + executor_with_default(const InnerExecutor& ex) noexcept |
| 35 | + : InnerExecutor(ex) |
| 36 | + { |
| 37 | + } |
71 | 38 |
|
72 | | - template <typename Initiation, typename RawCompletionToken, typename... Args> |
73 | | - static auto initiate(Initiation&& initiation, |
74 | | - RawCompletionToken&&, Args&&... args) |
| 39 | + /// Construct the adapted executor from the inner executor type. |
| 40 | + template <typename InnerExecutor1> |
| 41 | + executor_with_default(const InnerExecutor1& ex, |
| 42 | + typename std::enable_if< |
| 43 | + std::conditional< |
| 44 | + !std::is_same<InnerExecutor1, executor_with_default>::value, |
| 45 | + std::is_convertible<InnerExecutor1, InnerExecutor>, |
| 46 | + std::false_type |
| 47 | + >::type::value>::type = 0) noexcept |
| 48 | + : InnerExecutor(ex) |
75 | 49 | { |
76 | | - return awaitable_t< |
77 | | - std::decay_t<Initiation>, |
78 | | - std::decay_t<Args>...>( |
79 | | - std::forward<Initiation>(initiation), |
80 | | - std::make_tuple(std::forward<Args>(args)...)); |
81 | 50 | } |
| 51 | + }; |
| 52 | + |
| 53 | + /// Type alias to adapt an I/O object to use @c use_op_t as its |
| 54 | + /// default completion token type. |
| 55 | + template <typename T> |
| 56 | + using as_default_on_t = typename T::template rebind_executor< |
| 57 | + executor_with_default<typename T::executor_type> >::other; |
| 58 | + |
| 59 | + /// Function helper to adapt an I/O object to use @c use_op_t as its |
| 60 | + /// default completion token type. |
| 61 | + template <typename T> |
| 62 | + static typename std::decay_t<T>::template rebind_executor< |
| 63 | + executor_with_default<typename std::decay_t<T>::executor_type> |
| 64 | + >::other |
| 65 | + as_default_on(T && object) |
| 66 | + { |
| 67 | + return typename std::decay_t<T>::template rebind_executor< |
| 68 | + executor_with_default<typename std::decay_t<T>::executor_type> |
| 69 | + >::other(std::forward<T>(object)); |
| 70 | + } |
82 | 71 | }; |
| 72 | +constexpr as_io_awaitable_t as_io_awaitable; |
83 | 73 |
|
84 | 74 |
|
85 | | -#endif |
| 75 | +} |
86 | 76 |
|
| 77 | +#endif |
0 commit comments