include/boost/capy/ex/work_guard.hpp

100.0% Lines (31/0/31) 94.4% List of functions (34/0/36)
work_guard.hpp
f(x) Functions (36)
Function Calls Lines Blocks
boost::capy::work_guard<boost::capy::any_executor>::work_guard(boost::capy::any_executor) :85 4x 100.0% 100.0% boost::capy::work_guard<boost::capy::guard_test_executor>::work_guard(boost::capy::guard_test_executor) :85 10x 100.0% 100.0% boost::capy::work_guard<boost::capy::queue_executor>::work_guard(boost::capy::queue_executor) :85 7x 100.0% 100.0% boost::capy::work_guard<boost::capy::queuing_executor>::work_guard(boost::capy::queuing_executor) :85 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::work_guard(boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> >) :85 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::strand<boost::capy::thread_pool::executor_type> >::work_guard(boost::capy::strand<boost::capy::thread_pool::executor_type>) :85 4x 100.0% 100.0% boost::capy::work_guard<boost::capy::sync_executor>::work_guard(boost::capy::sync_executor) :85 25x 100.0% 100.0% boost::capy::work_guard<boost::capy::test::blocking_executor>::work_guard(boost::capy::test::blocking_executor) :85 1118x 100.0% 100.0% boost::capy::work_guard<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::work_guard(boost::capy::test::priority_executor<boost::capy::queuing_executor>) :85 2x 100.0% 100.0% boost::capy::work_guard<boost::capy::test_executor>::work_guard(boost::capy::test_executor) :85 113x 100.0% 100.0% boost::capy::work_guard<boost::capy::thread_pool::executor_type>::work_guard(boost::capy::thread_pool::executor_type) :85 676x 100.0% 100.0% boost::capy::work_guard<boost::capy::tracking_executor>::work_guard(boost::capy::tracking_executor) :85 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::guard_test_executor>::work_guard(boost::capy::work_guard<boost::capy::guard_test_executor> const&) :106 2x 100.0% 100.0% boost::capy::work_guard<boost::capy::guard_test_executor>::work_guard(boost::capy::work_guard<boost::capy::guard_test_executor>&&) :128 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::any_executor>::~work_guard() :143 4x 100.0% 100.0% boost::capy::work_guard<boost::capy::executor_ref>::~work_guard() :143 0 0.0% 0.0% boost::capy::work_guard<boost::capy::guard_test_executor>::~work_guard() :143 13x 100.0% 100.0% boost::capy::work_guard<boost::capy::queue_executor>::~work_guard() :143 7x 100.0% 100.0% boost::capy::work_guard<boost::capy::queuing_executor>::~work_guard() :143 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::~work_guard() :143 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::strand<boost::capy::thread_pool::executor_type> >::~work_guard() :143 4x 100.0% 100.0% boost::capy::work_guard<boost::capy::sync_executor>::~work_guard() :143 25x 100.0% 100.0% boost::capy::work_guard<boost::capy::test::blocking_executor>::~work_guard() :143 1118x 100.0% 100.0% boost::capy::work_guard<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::~work_guard() :143 2x 100.0% 100.0% boost::capy::work_guard<boost::capy::test_executor>::~work_guard() :143 113x 100.0% 100.0% boost::capy::work_guard<boost::capy::thread_pool::executor_type>::~work_guard() :143 676x 100.0% 100.0% boost::capy::work_guard<boost::capy::tracking_executor>::~work_guard() :143 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::any_executor>::executor() const :172 0 0.0% 0.0% boost::capy::work_guard<boost::capy::guard_test_executor>::executor() const :172 7x 100.0% 100.0% boost::capy::work_guard<boost::capy::test::blocking_executor>::executor() const :172 1538x 100.0% 100.0% boost::capy::work_guard<boost::capy::thread_pool::executor_type>::executor() const :172 1334x 100.0% 100.0% boost::capy::work_guard<boost::capy::guard_test_executor>::owns_work() const :186 12x 100.0% 100.0% boost::capy::work_guard<boost::capy::guard_test_executor>::reset() :204 4x 100.0% 100.0% boost::capy::work_guard<boost::capy::thread_pool::executor_type>::reset() :204 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::guard_test_executor> boost::capy::make_work_guard<boost::capy::guard_test_executor>(boost::capy::guard_test_executor) :227 1x 100.0% 100.0% boost::capy::work_guard<boost::capy::thread_pool::executor_type> boost::capy::make_work_guard<boost::capy::thread_pool::executor_type>(boost::capy::thread_pool::executor_type) :227 2x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/capy
9 //
10
11 #ifndef BOOST_CAPY_WORK_GUARD_HPP
12 #define BOOST_CAPY_WORK_GUARD_HPP
13
14 #include <boost/capy/detail/config.hpp>
15 #include <boost/capy/ex/execution_context.hpp>
16 #include <boost/capy/concept/executor.hpp>
17
18 #include <utility>
19
20 namespace boost {
21 namespace capy {
22
23 /** RAII guard that keeps an executor's context from completing.
24
25 This class holds "work" on an executor, preventing the associated
26 execution context's `run()` function from returning due to lack of
27 work. It calls `on_work_started()` on construction and
28 `on_work_finished()` on destruction, ensuring proper work tracking.
29
30 The guard is useful when you need to keep an execution context
31 running while waiting for external events or when work is
32 posted later.
33
34 @par RAII Semantics
35
36 @li Construction calls `ex.on_work_started()`.
37 @li Destruction calls `ex.on_work_finished()` if `owns_work()`.
38 @li Copy construction creates a new work reference (calls
39 `on_work_started()` again).
40 @li Move construction transfers ownership without additional calls.
41
42 @par Thread Safety
43
44 Distinct objects may be accessed concurrently. Access to a single
45 object requires external synchronization.
46
47 @par Example
48 @par !example work_guard
49
50
51 @note The executor is returned by reference, allowing callers to
52 manage the executor's lifetime directly. This is essential in
53 coroutine-first designs where the executor often outlives individual
54 coroutine frames.
55
56 @tparam Ex A type satisfying the Executor concept.
57
58 @see make_work_guard, Executor
59 */
60 template<Executor Ex>
61 class work_guard
62 {
63 Ex ex_;
64 bool owns_;
65
66 public:
67 /** Names the executor type this `work_guard<Ex>` guards. */
68 using executor_type = Ex;
69
70 /** Construct a work guard.
71
72 Calls `ex.on_work_started()` to inform the executor that
73 work is outstanding.
74
75 @par Exception Safety
76 No-throw guarantee.
77
78 @par Postconditions
79 @li `owns_work() == true`
80 @li `executor() == ex`
81
82 @param ex The executor to hold work on. Moved into the guard.
83 */
84 explicit
85 1962x work_guard(Ex ex) noexcept
86 1962x : ex_(std::move(ex))
87 1962x , owns_(true)
88 {
89 1962x ex_.on_work_started();
90 1962x }
91
92 /** Construct a copy.
93
94 Creates a new work guard holding work on the same executor.
95 Calls `on_work_started()` on the executor.
96
97 @par Exception Safety
98 No-throw guarantee.
99
100 @par Postconditions
101 @li `owns_work() == other.owns_work()`
102 @li `executor() == other.executor()`
103
104 @param other The work guard to copy from.
105 */
106 2x work_guard(work_guard const& other) noexcept
107 2x : ex_(other.ex_)
108 2x , owns_(other.owns_)
109 {
110 2x if(owns_)
111 1x ex_.on_work_started();
112 2x }
113
114 /** Construct by moving.
115
116 Transfers work ownership from `other` to `*this`. Does not
117 call `on_work_started()` or `on_work_finished()`.
118
119 @par Exception Safety
120 No-throw guarantee.
121
122 @par Postconditions
123 @li `owns_work()` equals the prior value of `other.owns_work()`
124 @li `other.owns_work() == false`
125
126 @param other The work guard to move from.
127 */
128 1x work_guard(work_guard&& other) noexcept
129 1x : ex_(std::move(other.ex_))
130 1x , owns_(other.owns_)
131 {
132 1x other.owns_ = false;
133 1x }
134
135 /** Destructor.
136
137 If `owns_work()` is `true`, calls `on_work_finished()` on
138 the executor.
139
140 @par Exception Safety
141 No-throw guarantee.
142 */
143 1965x ~work_guard()
144 {
145 1965x if(owns_)
146 1959x ex_.on_work_finished();
147 1965x }
148
149 /** Copy assignment is disabled.
150
151 A guard takes its work reference at construction and releases it at
152 destruction or through @ref reset. No operation rebinds an existing
153 guard to a different executor.
154
155 @param other The work guard that would be assigned from.
156
157 @return A reference to `*this`.
158 */
159 work_guard& operator=(work_guard const& other) = delete;
160
161 /** Return the underlying executor by reference.
162
163 The reference remains valid for the lifetime of this guard,
164 enabling callers to manage executor lifetime explicitly.
165
166 @par Exception Safety
167 No-throw guarantee.
168
169 @return A reference to the stored executor.
170 */
171 executor_type const&
172 3907x executor() const noexcept
173 {
174 3907x return ex_;
175 }
176
177 /** Return whether the guard owns work.
178
179 @par Exception Safety
180 No-throw guarantee.
181
182 @return `true` if this guard calls `on_work_finished()`
183 on destruction, `false` otherwise.
184 */
185 bool
186 12x owns_work() const noexcept
187 {
188 12x return owns_;
189 }
190
191 /** Release ownership of the work.
192
193 If `owns_work()` is `true`, calls `on_work_finished()` on
194 the executor and sets ownership to `false`. Otherwise, has
195 no effect.
196
197 @par Exception Safety
198 No-throw guarantee.
199
200 @par Postconditions
201 @li `owns_work() == false`
202 */
203 void
204 5x reset() noexcept
205 {
206 5x if(owns_)
207 {
208 4x ex_.on_work_finished();
209 4x owns_ = false;
210 }
211 5x }
212 };
213
214 /** Create a work guard from an executor.
215
216 @par Exception Safety
217 No-throw guarantee.
218
219 @param ex The executor to create the guard for.
220
221 @return A `work_guard` holding work on `ex`.
222
223 @see work_guard
224 */
225 template<Executor Ex>
226 work_guard<Ex>
227 3x make_work_guard(Ex ex)
228 {
229 3x return work_guard<Ex>(std::move(ex));
230 }
231
232 } // capy
233 } // boost
234
235 #endif
236