GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 40 / 0 / 40
Functions: 100.0% 10 / 0 / 10
Branches: -% 0 / 0 / 0

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