GCC Code Coverage Report


Directory: ./
File: libs/capy/include/boost/capy/ex/run_sync.hpp
Date: 2026-01-18 18:26:31
Exec Total Coverage
Lines: 25 32 78.1%
Functions: 5 10 50.0%
Branches: 8 8 100.0%

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_SYNC_HPP
11 #define BOOST_CAPY_RUN_SYNC_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/ex/any_coro.hpp>
15 #include <boost/capy/ex/execution_context.hpp>
16 #include <boost/capy/task.hpp>
17
18 #include <coroutine>
19 #include <exception>
20 #include <type_traits>
21 #include <utility>
22
23 namespace boost {
24 namespace capy {
25
26 namespace detail {
27
28 /** Trivial execution context for synchronous execution. */
29 class sync_context : public execution_context
30 {
31 };
32
33 /** Trivial executor for synchronous execution.
34
35 Returns the coroutine handle directly for symmetric transfer,
36 enabling inline execution without scheduling.
37 */
38 struct sync_executor
39 {
40 static sync_context ctx_;
41
42 bool operator==(sync_executor const&) const noexcept { return true; }
43 execution_context& context() const noexcept { return ctx_; }
44 void on_work_started() const noexcept {}
45 void on_work_finished() const noexcept {}
46
47 23 any_coro dispatch(any_coro h) const
48 {
49 23 return h;
50 }
51
52 void post(any_coro h) const
53 {
54 h.resume();
55 }
56 };
57
58 inline sync_context sync_executor::ctx_;
59
60 /** Synchronous task runner.
61
62 Runs a coroutine task to completion on the caller's thread,
63 returning the result directly or rethrowing any exception.
64
65 This class is not intended for direct use. Use the `run_sync()`
66 factory function instead.
67
68 @par Thread Safety
69 Not thread-safe. The task runs entirely on the calling thread.
70
71 @see run_sync
72 */
73 class sync_runner
74 {
75 public:
76 sync_runner() = default;
77
78 sync_runner(sync_runner const&) = delete;
79 sync_runner& operator=(sync_runner const&) = delete;
80 sync_runner(sync_runner&&) = default;
81 sync_runner& operator=(sync_runner&&) = default;
82
83 /** Run a task to completion and return the result.
84
85 Executes the task synchronously on the calling thread. The task
86 runs to completion before this function returns.
87
88 @par Exception Safety
89 If the task throws an exception, it is rethrown to the caller.
90
91 @param t The task to execute.
92
93 @return The value returned by the task.
94
95 @throws Any exception thrown by the task.
96 */
97 template<typename T>
98 46 T operator()(task<T> t) &&
99 {
100 46 auto h = t.release();
101 sync_executor ex;
102
103 46 h.promise().continuation_ = std::noop_coroutine();
104 46 h.promise().ex_ = ex;
105 46 h.promise().caller_ex_ = ex;
106 46 h.promise().needs_dispatch_ = false;
107
108
1/1
✓ Branch 3 taken 23 times.
46 ex.dispatch(any_coro{h}).resume();
109
110 46 std::exception_ptr ep = h.promise().ep_;
111
112 if constexpr (std::is_void_v<T>)
113 {
114
1/1
✓ Branch 1 taken 7 times.
14 h.destroy();
115
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
14 if (ep)
116 4 std::rethrow_exception(ep);
117 }
118 else
119 {
120
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 13 times.
32 if (ep)
121 {
122
1/1
✓ Branch 1 taken 3 times.
6 h.destroy();
123 12 std::rethrow_exception(ep);
124 }
125 26 auto& result_base = static_cast<detail::task_return_base<T>&>(
126 26 h.promise());
127 26 auto result = std::move(*result_base.result_);
128
1/1
✓ Branch 1 taken 13 times.
26 h.destroy();
129 30 return result;
130 4 }
131 46 }
132 };
133
134 } // namespace detail
135
136 /** Create a synchronous task runner.
137
138 Returns a runner that executes a coroutine task to completion
139 on the caller's thread. The task completes before this function
140 returns, and the result is returned directly.
141
142 @par Usage
143 @code
144 // Run a task and get the result
145 int value = run_sync()(compute_value());
146
147 // Run a void task
148 run_sync()(do_work());
149
150 // Exceptions propagate normally
151 try {
152 run_sync()(failing_task());
153 } catch (std::exception const& e) {
154 // handle error
155 }
156 @endcode
157
158 @par Thread Safety
159 The task runs entirely on the calling thread. No executor or
160 execution context is required.
161
162 @return A runner object with `operator()(task<T>)` that returns `T`.
163
164 @see task
165 @see run_async
166 @see run_on
167 */
168 inline
169 detail::sync_runner
170 23 run_sync()
171 {
172 23 return detail::sync_runner{};
173 }
174
175 } // namespace capy
176 } // namespace boost
177
178 #endif
179