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 2x 100.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 16959x 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() :125 3528x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::(anonymous namespace)::counting_executor, 0>(boost::capy::(anonymous namespace)::counting_executor const&) :164 1x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::any_executor, 0>(boost::capy::any_executor const&) :164 24x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::queue_executor, 0>(boost::capy::queue_executor const&) :164 7x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::queuing_executor, 0>(boost::capy::queuing_executor const&) :164 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&) :164 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&) :164 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&) :164 6x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::sync_executor, 0>(boost::capy::sync_executor const&) :164 25x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::test::blocking_executor, 0>(boost::capy::test::blocking_executor const&) :164 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&) :164 6x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::test_executor, 0>(boost::capy::test_executor const&) :164 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&) :164 31057x 100.0% 100.0% boost::capy::executor_ref::executor_ref<boost::capy::tracking_executor, 0>(boost::capy::tracking_executor const&) :164 1x 100.0% 100.0% boost::capy::executor_ref::operator bool() const :175 6x 100.0% 100.0% boost::capy::executor_ref::context() const :186 1x 100.0% 100.0% boost::capy::executor_ref::on_work_started() const :197 1x 100.0% 100.0% boost::capy::executor_ref::on_work_finished() const :207 1x 100.0% 100.0% boost::capy::executor_ref::dispatch(boost::capy::continuation&) const :226 122x 100.0% 100.0% boost::capy::executor_ref::post(boost::capy::continuation&) const :242 17305x 100.0% 100.0% boost::capy::executor_ref::operator==(boost::capy::executor_ref const&) const :256 7x 100.0% 100.0% boost::capy::thread_pool::executor_type const* boost::capy::executor_ref::target<boost::capy::thread_pool::executor_type>() const :279 2x 100.0% 100.0% boost::capy::thread_pool::executor_type* boost::capy::executor_ref::target<boost::capy::thread_pool::executor_type>() :288 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 34610x [](void const* p, continuation& c) {
58 17305x 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 @code
99 void store_executor(executor_ref ex)
100 {
101 if(ex)
102 ex.post(my_continuation);
103 }
104
105 thread_pool ctx;
106 store_executor(ctx.get_executor());
107 @endcode
108
109 @see any_executor, Executor
110 */
111 class executor_ref
112 {
113 void const* ex_ = nullptr;
114 detail::executor_vtable const* vt_ = nullptr;
115
116 public:
117 /** Construct a default instance.
118
119 Constructs an empty `executor_ref`. `operator bool()` and
120 `operator==()` report the empty state; `context()`,
121 `on_work_started()`, `on_work_finished()`, `dispatch()`,
122 `post()`, and `target()` are undefined behavior until an
123 executor is assigned.
124 */
125 3528x executor_ref() = default;
126
127 /** Construct a copy.
128
129 Copies the internal pointers, preserving identity.
130 This enables the same-executor optimization when passing
131 executor_ref through coroutine chains.
132
133 @param other The reference to copy.
134 */
135 executor_ref(executor_ref const& other) = default;
136
137 /** Copy assignment operator.
138
139 @param other The reference to copy.
140
141 @return A reference to `*this`.
142 */
143 executor_ref& operator=(executor_ref const& other) = default;
144
145 /** Constructs from any executor type.
146
147 Captures a reference to the given executor and stores a pointer
148 to the type-specific vtable. The executor must remain valid for
149 the lifetime of this `executor_ref` instance.
150
151 @param ex The executor to wrap. Must satisfy the `Executor`
152 concept. A pointer to this object is stored
153 internally; the executor must outlive this wrapper.
154 */
155 #if defined(__GNUC__) && !defined(__clang__)
156 // GCC constraint satisfaction caching bug workaround
157 template<class Ex,
158 std::enable_if_t<!std::is_same_v<
159 std::decay_t<Ex>, executor_ref>, int> = 0>
160 #else
161 template<class Ex>
162 requires (!std::same_as<std::decay_t<Ex>, executor_ref>)
163 #endif
164 32430x executor_ref(Ex const& ex) noexcept
165 32430x : ex_(&ex)
166 32430x , vt_(&detail::vtable_for<Ex>)
167 {
168 32430x }
169
170 /** Returns true if this instance holds a valid executor.
171
172 @return `true` if constructed with an executor, `false` if
173 default-constructed.
174 */
175 6x explicit operator bool() const noexcept
176 {
177 6x return ex_ != nullptr;
178 }
179
180 /** Returns a reference to the associated execution context.
181
182 @return A reference to the execution context.
183
184 @pre This instance was constructed with a valid executor.
185 */
186 1x execution_context& context() const noexcept
187 {
188 1x return vt_->context(ex_);
189 }
190
191 /** Informs the executor that work is beginning.
192
193 Must be paired with a subsequent call to `on_work_finished()`.
194
195 @pre This instance was constructed with a valid executor.
196 */
197 1x void on_work_started() const noexcept
198 {
199 1x vt_->on_work_started(ex_);
200 1x }
201
202 /** Informs the executor that work has completed.
203
204 @pre A preceding call to `on_work_started()` was made.
205 @pre This instance was constructed with a valid executor.
206 */
207 1x void on_work_finished() const noexcept
208 {
209 1x vt_->on_work_finished(ex_);
210 1x }
211
212 /** Dispatches a continuation through the wrapped executor.
213
214 Returns a handle for symmetric transfer. If running in the
215 executor's thread, returns `c.h`. Otherwise, posts the
216 continuation for later execution and returns
217 `std::noop_coroutine()`.
218
219 @param c The continuation to dispatch for resumption.
220 Must remain at a stable address until dequeued.
221
222 @return A handle for symmetric transfer or `std::noop_coroutine()`.
223
224 @pre This instance was constructed with a valid executor.
225 */
226 122x std::coroutine_handle<> dispatch(continuation& c) const
227 {
228 122x return vt_->dispatch(ex_, c);
229 }
230
231 /** Posts a continuation to the wrapped executor.
232
233 Posts the continuation to the executor for later execution
234 and returns. The caller should transfer to `std::noop_coroutine()`
235 after calling this.
236
237 @param c The continuation to post for resumption.
238 Must remain at a stable address until dequeued.
239
240 @pre This instance was constructed with a valid executor.
241 */
242 17305x void post(continuation& c) const
243 {
244 17305x vt_->post(ex_, c);
245 17305x }
246
247 /** Compares two executor references for equality.
248
249 Two `executor_ref` instances are equal if they wrap
250 executors of the same type that compare equal.
251
252 @param other The executor reference to compare against.
253
254 @return `true` if both wrap equal executors of the same type.
255 */
256 7x bool operator==(executor_ref const& other) const noexcept
257 {
258 7x if (ex_ == other.ex_)
259 5x return true;
260 2x if (vt_ != other.vt_)
261 1x return false;
262 1x return vt_->equals(ex_, other.ex_);
263 }
264
265 /** Return a pointer to the wrapped executor if it matches
266 the requested type.
267
268 Performs a type check against the stored executor and
269 returns a typed pointer when the types match, or
270 `nullptr` otherwise. Analogous to
271 `std::any_cast< Executor >( &a )`.
272
273 @tparam Executor The executor type to retrieve.
274
275 @return A pointer to the underlying executor, or
276 `nullptr` if the type does not match.
277 */
278 template< typename Executor >
279 2x const Executor* target() const
280 {
281 2x if ( *vt_->type_id == detail::type_id< Executor >() )
282 1x return static_cast< Executor const* >( ex_ );
283 1x return nullptr;
284 }
285
286 /// @copydoc target() const
287 template< typename Executor>
288 2x Executor* target()
289 {
290 2x if ( *vt_->type_id == detail::type_id< Executor >() )
291 return const_cast< Executor* >(
292 1x static_cast< Executor const* >( ex_ ));
293 1x return nullptr;
294 }
295 };
296
297 } // capy
298 } // boost
299
300 #endif
301