libs/capy/include/boost/capy/ex/run_on.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // | ||
| 2 | // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com) | ||
| 3 | // | ||
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
| 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| 6 | // | ||
| 7 | // Official repository: https://github.com/cppalliance/capy | ||
| 8 | // | ||
| 9 | |||
| 10 | #ifndef BOOST_CAPY_RUN_ON_HPP | ||
| 11 | #define BOOST_CAPY_RUN_ON_HPP | ||
| 12 | |||
| 13 | #include <boost/capy/detail/config.hpp> | ||
| 14 | #include <boost/capy/concept/executor.hpp> | ||
| 15 | #include <boost/capy/io_awaitable.hpp> | ||
| 16 | #include <boost/capy/ex/executor_ref.hpp> | ||
| 17 | |||
| 18 | #include <stop_token> | ||
| 19 | #include <utility> | ||
| 20 | |||
| 21 | namespace boost { | ||
| 22 | namespace capy { | ||
| 23 | namespace detail { | ||
| 24 | |||
| 25 | /** Awaitable that binds an IoAwaitableTask to a specific executor. | ||
| 26 | |||
| 27 | Stores the executor and inner task by value. When co_awaited, the | ||
| 28 | co_await expression's lifetime extension keeps both alive for the | ||
| 29 | duration of the operation. | ||
| 30 | |||
| 31 | @tparam Task The IoAwaitableTask type | ||
| 32 | @tparam Ex The executor type | ||
| 33 | */ | ||
| 34 | template<IoLaunchableTask Task, Executor Ex> | ||
| 35 | struct [[nodiscard]] | ||
| 36 | run_on_awaitable | ||
| 37 | { | ||
| 38 | Ex ex_; | ||
| 39 | Task inner_; | ||
| 40 | |||
| 41 | 2 | run_on_awaitable(Ex ex, Task inner) | |
| 42 | 2 | : ex_(std::move(ex)) | |
| 43 | 2 | , inner_(std::move(inner)) | |
| 44 | { | ||
| 45 | 2 | } | |
| 46 | |||
| 47 | 2 | bool await_ready() const noexcept | |
| 48 | { | ||
| 49 | 2 | return inner_.await_ready(); | |
| 50 | } | ||
| 51 | |||
| 52 | 2 | auto await_resume() | |
| 53 | { | ||
| 54 | 2 | return inner_.await_resume(); | |
| 55 | } | ||
| 56 | |||
| 57 | // IoAwaitable: receives caller's executor and stop_token for completion dispatch | ||
| 58 | template<typename Caller> | ||
| 59 | 2 | coro await_suspend(coro cont, Caller const& caller_ex, std::stop_token token) | |
| 60 | { | ||
| 61 | 2 | auto h = inner_.handle(); | |
| 62 | 2 | auto& p = h.promise(); | |
| 63 | 2 | p.set_executor(ex_); | |
| 64 | 2 | p.set_continuation(cont, caller_ex); | |
| 65 | 2 | p.set_stop_token(token); | |
| 66 | 2 | return h; | |
| 67 | } | ||
| 68 | |||
| 69 | // Non-copyable | ||
| 70 | run_on_awaitable(run_on_awaitable const&) = delete; | ||
| 71 | run_on_awaitable& operator=(run_on_awaitable const&) = delete; | ||
| 72 | |||
| 73 | // Movable | ||
| 74 | 2 | run_on_awaitable(run_on_awaitable&& other) noexcept | |
| 75 | 2 | : ex_(std::move(other.ex_)) | |
| 76 | 2 | , inner_(std::move(other.inner_)) | |
| 77 | { | ||
| 78 | 2 | } | |
| 79 | |||
| 80 | run_on_awaitable& operator=(run_on_awaitable&& other) noexcept | ||
| 81 | { | ||
| 82 | if(this != &other) | ||
| 83 | { | ||
| 84 | ex_ = std::move(other.ex_); | ||
| 85 | inner_ = std::move(other.inner_); | ||
| 86 | } | ||
| 87 | return *this; | ||
| 88 | } | ||
| 89 | }; | ||
| 90 | |||
| 91 | } // namespace detail | ||
| 92 | |||
| 93 | /** Binds a task to execute on a specific executor. | ||
| 94 | |||
| 95 | The executor is stored by value in the returned awaitable. | ||
| 96 | When co_awaited, the inner task receives this executor through | ||
| 97 | direct promise configuration. | ||
| 98 | |||
| 99 | @param ex The executor on which the task should run (copied by value). | ||
| 100 | @param t The IoAwaitableTask to bind to the executor. | ||
| 101 | |||
| 102 | @return An awaitable that runs t on the specified executor. | ||
| 103 | */ | ||
| 104 | template<Executor Ex, IoLaunchableTask Task> | ||
| 105 | 2 | [[nodiscard]] auto run_on(Ex ex, Task t) | |
| 106 | { | ||
| 107 | return detail::run_on_awaitable<Task, Ex>{ | ||
| 108 | 2 | std::move(ex), std::move(t)}; | |
| 109 | } | ||
| 110 | |||
| 111 | } // namespace capy | ||
| 112 | } // namespace boost | ||
| 113 | |||
| 114 | #endif | ||
| 115 |