include/boost/capy/ex/executor_ref.hpp

100.0% Lines (46/0/46) 39.6% List of functions (40/0/101)
executor_ref.hpp
f(x) Functions (101)
Function Calls Lines Blocks
boost::capy::detail::vtable_for<boost::capy::(anonymous namespace)::counting_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::any_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queue_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queuing_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::executor_ref> >::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::thread_pool::executor_type> >::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::sync_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::blocking_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 1x 50.0% 100.0% boost::capy::detail::vtable_for<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::thread_pool::executor_type>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::tracking_executor>::{lambda(void const*)#1}::operator()(void const*) const :45 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::(anonymous namespace)::counting_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 1x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::any_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queue_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queuing_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::executor_ref> >::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::thread_pool::executor_type> >::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::sync_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::blocking_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::thread_pool::executor_type>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::tracking_executor>::{lambda(void const*)#2}::operator()(void const*) const :49 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::(anonymous namespace)::counting_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 1x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::any_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queue_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queuing_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::executor_ref> >::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::thread_pool::executor_type> >::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::sync_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::blocking_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::thread_pool::executor_type>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::tracking_executor>::{lambda(void const*)#3}::operator()(void const*) const :53 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::(anonymous namespace)::counting_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::any_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 1x 50.0% 100.0% boost::capy::detail::vtable_for<boost::capy::queue_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queuing_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 31x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::executor_ref> >::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 1x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::thread_pool::executor_type> >::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 6x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::sync_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::blocking_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 122x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 4x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::test_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 180x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::thread_pool::executor_type>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 17367x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::tracking_executor>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const :57 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::(anonymous namespace)::counting_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::any_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queue_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queuing_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 1x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::executor_ref> >::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::thread_pool::executor_type> >::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 3x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::sync_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::blocking_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 44x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 67x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::thread_pool::executor_type>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 7x 100.0% 100.0% boost::capy::detail::vtable_for<boost::capy::tracking_executor>::{lambda(void const*, boost::capy::continuation&)#2}::operator()(void const*, boost::capy::continuation&) const :61 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::(anonymous namespace)::counting_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::any_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queue_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::queuing_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::executor_ref> >::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > >::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::strand<boost::capy::thread_pool::executor_type> >::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::sync_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::blocking_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test::priority_executor<boost::capy::queuing_executor> >::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::test_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::detail::vtable_for<boost::capy::thread_pool::executor_type>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 1x 50.0% 100.0% boost::capy::detail::vtable_for<boost::capy::tracking_executor>::{lambda(void const*, void const*)#1}::operator()(void const*, void const*) const :65 0 0.0% 0.0% boost::capy::executor_ref::executor_ref() :117 3546x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::(anonymous namespace)::counting_executor, 0>(boost::capy::(anonymous namespace)::counting_executor const&) :156 1x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::any_executor, 0>(boost::capy::any_executor const&) :156 24x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::queue_executor, 0>(boost::capy::queue_executor const&) :156 7x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::queuing_executor, 0>(boost::capy::queuing_executor const&) :156 36x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::strand<boost::capy::executor_ref>, 0>(boost::capy::strand<boost::capy::executor_ref> const&) :156 1x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> >, 0>(boost::capy::strand<boost::capy::test::priority_executor<boost::capy::queuing_executor> > const&) :156 1x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::strand<boost::capy::thread_pool::executor_type>, 0>(boost::capy::strand<boost::capy::thread_pool::executor_type> const&) :156 6x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::sync_executor, 0>(boost::capy::sync_executor const&) :156 25x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::test::blocking_executor, 0>(boost::capy::test::blocking_executor const&) :156 1122x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::test::priority_executor<boost::capy::queuing_executor>, 0>(boost::capy::test::priority_executor<boost::capy::queuing_executor> const&) :156 6x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::test_executor, 0>(boost::capy::test_executor const&) :156 143x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::thread_pool::executor_type, 0>(boost::capy::thread_pool::executor_type const&) :156 31066x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::tracking_executor, 0>(boost::capy::tracking_executor const&) :156 1x 100.0% 100.0% boost::capy::executor_ref::operator bool() const :167 6x 100.0% 100.0% boost::capy::executor_ref::context() const :178 1x 100.0% 100.0% boost::capy::executor_ref::on_work_started() const :189 1x 100.0% 100.0% boost::capy::executor_ref::on_work_finished() const :199 1x 100.0% 100.0% boost::capy::executor_ref::dispatch(boost::capy::continuation&) const :218 122x 100.0% 100.0% boost::capy::executor_ref::post(boost::capy::continuation&) const :234 17712x 100.0% 100.0% boost::capy::executor_ref::operator==(boost::capy::executor_ref const&) const :248 7x 100.0% 100.0% boost::capy::thread_pool::executor_type const* boost::capy::executor_ref::target<boost::capy::thread_pool::executor_type>() const :271 2x 100.0% 100.0% boost::capy::thread_pool::executor_type* boost::capy::executor_ref::target<boost::capy::thread_pool::executor_type>() :280 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_EXECUTOR_REF_HPP
12 #define BOOST_CAPY_EXECUTOR_REF_HPP
13
14 #include <boost/capy/detail/config.hpp>
15 #include <boost/capy/detail/type_id.hpp>
16 #include <boost/capy/continuation.hpp>
17 #include <concepts>
18 #include <coroutine>
19 #include <type_traits>
20 #include <utility>
21
22 namespace boost {
23 namespace capy {
24
25 class execution_context;
26
27 namespace detail {
28
29 /** Virtual function table for type-erased executor operations. */
30 struct executor_vtable
31 {
32 execution_context& (*context)(void const*) noexcept;
33 void (*on_work_started)(void const*) noexcept;
34 void (*on_work_finished)(void const*) noexcept;
35 void (*post)(void const*, continuation&);
36 std::coroutine_handle<> (*dispatch)(void const*, continuation&);
37 bool (*equals)(void const*, void const*) noexcept;
38 detail::type_info const* type_id;
39 };
40
41 /** Vtable instance for a specific executor type. */
42 template<class Ex>
43 inline constexpr executor_vtable vtable_for = {
44 // context
45 1x [](void const* p) noexcept -> execution_context& {
46 1x return const_cast<Ex*>(static_cast<Ex const*>(p))->context();
47 },
48 // on_work_started
49 2x [](void const* p) noexcept {
50 1x const_cast<Ex*>(static_cast<Ex const*>(p))->on_work_started();
51 },
52 // on_work_finished
53 2x [](void const* p) noexcept {
54 1x const_cast<Ex*>(static_cast<Ex const*>(p))->on_work_finished();
55 },
56 // post
57 35424x [](void const* p, continuation& c) {
58 17712x static_cast<Ex const*>(p)->post(c);
59 },
60 // dispatch
61 122x [](void const* p, continuation& c) -> std::coroutine_handle<> {
62 122x return static_cast<Ex const*>(p)->dispatch(c);
63 },
64 // equals
65 1x [](void const* a, void const* b) noexcept -> bool {
66 1x return *static_cast<Ex const*>(a) == *static_cast<Ex const*>(b);
67 },
68 // type_id
69 &detail::type_id<Ex>()
70 };
71
72 } // detail
73
74 /** Forwards `dispatch`/`post`/`context` calls through a non-owning, type-erased executor pointer.
75
76 This class provides type erasure for any executor type, enabling
77 runtime polymorphism without virtual functions or allocation.
78 It stores a pointer to the original executor and a pointer to a
79 static vtable. Executors of different types are therefore stored
80 uniformly, while satisfying the full `Executor` concept.
81
82 @par Reference Semantics
83 This class has reference semantics: it does not allocate or own
84 the wrapped executor. Copy operations copy the internal
85 pointers. The caller must ensure the referenced executor outlives
86 all `executor_ref` instances that wrap it.
87
88 @par Thread Safety
89 The `executor_ref` itself is not thread-safe for concurrent
90 modification, but its executor operations are safe to call
91 concurrently if the underlying executor supports it.
92
93 @par Executor Concept
94 This class satisfies the `Executor` concept, making it usable
95 anywhere a concrete executor is expected.
96
97 @par Example
98 @par !example example
99
100
101 @see any_executor, Executor
102 */
103 class executor_ref
104 {
105 void const* ex_ = nullptr;
106 detail::executor_vtable const* vt_ = nullptr;
107
108 public:
109 /** Construct a default instance.
110
111 Constructs an empty `executor_ref`. `operator bool()` and
112 `operator==()` report the empty state; `context()`,
113 `on_work_started()`, `on_work_finished()`, `dispatch()`,
114 `post()`, and `target()` are undefined behavior until an
115 executor is assigned.
116 */
117 3546x executor_ref() = default;
118
119 /** Construct a copy.
120
121 Copies the internal pointers, preserving identity.
122 This enables the same-executor optimization when passing
123 executor_ref through coroutine chains.
124
125 @param other The reference to copy.
126 */
127 executor_ref(executor_ref const& other) = default;
128
129 /** Copy assignment operator.
130
131 @param other The reference to copy.
132
133 @return A reference to `*this`.
134 */
135 executor_ref& operator=(executor_ref const& other) = default;
136
137 /** Constructs from any executor type.
138
139 Captures a reference to the given executor and stores a pointer
140 to the type-specific vtable. The executor must remain valid for
141 the lifetime of this `executor_ref` instance.
142
143 @param ex The executor to wrap. Must satisfy the `Executor`
144 concept. A pointer to this object is stored
145 internally; the executor must outlive this wrapper.
146 */
147 #if defined(__GNUC__) && !defined(__clang__)
148 // GCC constraint satisfaction caching bug workaround
149 template<class Ex,
150 std::enable_if_t<!std::is_same_v<
151 std::decay_t<Ex>, executor_ref>, int> = 0>
152 #else
153 template<class Ex>
154 requires (!std::same_as<std::decay_t<Ex>, executor_ref>)
155 #endif
156 32439x executor_ref(Ex const& ex) noexcept
157 32439x : ex_(&ex)
158 32439x , vt_(&detail::vtable_for<Ex>)
159 {
160 32439x }
161
162 /** Returns true if this instance holds a valid executor.
163
164 @return `true` if constructed with an executor, `false` if
165 default-constructed.
166 */
167 6x explicit operator bool() const noexcept
168 {
169 6x return ex_ != nullptr;
170 }
171
172 /** Returns a reference to the associated execution context.
173
174 @return A reference to the execution context.
175
176 @pre This instance was constructed with a valid executor.
177 */
178 1x execution_context& context() const noexcept
179 {
180 1x return vt_->context(ex_);
181 }
182
183 /** Informs the executor that work is beginning.
184
185 Must be paired with a subsequent call to `on_work_finished()`.
186
187 @pre This instance was constructed with a valid executor.
188 */
189 1x void on_work_started() const noexcept
190 {
191 1x vt_->on_work_started(ex_);
192 1x }
193
194 /** Informs the executor that work has completed.
195
196 @pre A preceding call to `on_work_started()` was made.
197 @pre This instance was constructed with a valid executor.
198 */
199 1x void on_work_finished() const noexcept
200 {
201 1x vt_->on_work_finished(ex_);
202 1x }
203
204 /** Dispatches a continuation through the wrapped executor.
205
206 Returns a handle for symmetric transfer. If running in the
207 executor's thread, returns `c.h`. Otherwise, posts the
208 continuation for later execution and returns
209 `std::noop_coroutine()`.
210
211 @param c The continuation to dispatch for resumption.
212 Must remain at a stable address until dequeued.
213
214 @return A handle for symmetric transfer or `std::noop_coroutine()`.
215
216 @pre This instance was constructed with a valid executor.
217 */
218 122x std::coroutine_handle<> dispatch(continuation& c) const
219 {
220 122x return vt_->dispatch(ex_, c);
221 }
222
223 /** Posts a continuation to the wrapped executor.
224
225 Posts the continuation to the executor for later execution
226 and returns. The caller should transfer to `std::noop_coroutine()`
227 after calling this.
228
229 @param c The continuation to post for resumption.
230 Must remain at a stable address until dequeued.
231
232 @pre This instance was constructed with a valid executor.
233 */
234 17712x void post(continuation& c) const
235 {
236 17712x vt_->post(ex_, c);
237 17712x }
238
239 /** Compares two executor references for equality.
240
241 Two `executor_ref` instances are equal if they wrap
242 executors of the same type that compare equal.
243
244 @param other The executor reference to compare against.
245
246 @return `true` if both wrap equal executors of the same type.
247 */
248 7x bool operator==(executor_ref const& other) const noexcept
249 {
250 7x if (ex_ == other.ex_)
251 5x return true;
252 2x if (vt_ != other.vt_)
253 1x return false;
254 1x return vt_->equals(ex_, other.ex_);
255 }
256
257 /** Return a pointer to the wrapped executor if it matches
258 the requested type.
259
260 Performs a type check against the stored executor and
261 returns a typed pointer when the types match, or
262 `nullptr` otherwise. Analogous to
263 `std::any_cast< Executor >( &a )`.
264
265 @tparam Executor The executor type to retrieve.
266
267 @return A pointer to the underlying executor, or
268 `nullptr` if the type does not match.
269 */
270 template< typename Executor >
271 2x const Executor* target() const
272 {
273 2x if ( *vt_->type_id == detail::type_id< Executor >() )
274 1x return static_cast< Executor const* >( ex_ );
275 1x return nullptr;
276 }
277
278 /// @copydoc target() const
279 template< typename Executor>
280 2x Executor* target()
281 {
282 2x if ( *vt_->type_id == detail::type_id< Executor >() )
283 return const_cast< Executor* >(
284 1x static_cast< Executor const* >( ex_ ));
285 1x return nullptr;
286 }
287 };
288
289 } // capy
290 } // boost
291
292 #endif
293