include/boost/capy/asio/spawn.hpp

100.0% Lines (10/10) 100.0% List of functions (6/6)
spawn.hpp
f(x) Functions (6)
Function Calls Lines Blocks
boost::capy::asio_spawn_op<boost::capy::test_executor, boost::capy::task<void> >::asio_spawn_op(boost::capy::test_executor, boost::capy::task<void>) :107 1x 100.0% 100.0% boost::capy::asio_spawn_op<boost::capy::thread_pool::executor_type, boost::capy::noexcept_awaitable<boost::capy::test::read_stream::read_some<boost::capy::detail::asio_boost_buffer_range<boost::asio::mutable_buffer> >(boost::capy::detail::asio_boost_buffer_range<boost::asio::mutable_buffer>)::awaitable> >::asio_spawn_op(boost::capy::thread_pool::executor_type, boost::capy::noexcept_awaitable<boost::capy::test::read_stream::read_some<boost::capy::detail::asio_boost_buffer_range<boost::asio::mutable_buffer> >(boost::capy::detail::asio_boost_buffer_range<boost::asio::mutable_buffer>)::awaitable>) :107 2x 100.0% 100.0% boost::capy::asio_spawn_op<boost::capy::thread_pool::executor_type, boost::capy::noexcept_awaitable<boost::capy::test::write_stream::write_some<boost::capy::detail::asio_boost_buffer_range<boost::asio::const_buffer> >(boost::capy::detail::asio_boost_buffer_range<boost::asio::const_buffer>)::awaitable> >::asio_spawn_op(boost::capy::thread_pool::executor_type, boost::capy::noexcept_awaitable<boost::capy::test::write_stream::write_some<boost::capy::detail::asio_boost_buffer_range<boost::asio::const_buffer> >(boost::capy::detail::asio_boost_buffer_range<boost::asio::const_buffer>)::awaitable>) :107 1x 100.0% 100.0% auto boost::capy::asio_spawn_op<boost::capy::test_executor, boost::capy::task<void> >::operator()<boost::asio::use_future_t<std::allocator<void> > >(boost::asio::use_future_t<std::allocator<void> >&&) :118 1x 100.0% 82.0% auto boost::capy::asio_spawn_op<boost::capy::thread_pool::executor_type, boost::capy::noexcept_awaitable<boost::capy::test::read_stream::read_some<boost::capy::detail::asio_boost_buffer_range<boost::asio::mutable_buffer> >(boost::capy::detail::asio_boost_buffer_range<boost::asio::mutable_buffer>)::awaitable> >::operator()<boost::asio::detail::read_op<boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>, boost::asio::mutable_buffer, boost::asio::mutable_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#2}> >(boost::asio::detail::read_op<boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>, boost::asio::mutable_buffer, boost::asio::mutable_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#2}>&&) :118 2x 100.0% 100.0% auto boost::capy::asio_spawn_op<boost::capy::thread_pool::executor_type, boost::capy::noexcept_awaitable<boost::capy::test::write_stream::write_some<boost::capy::detail::asio_boost_buffer_range<boost::asio::const_buffer> >(boost::capy::detail::asio_boost_buffer_range<boost::asio::const_buffer>)::awaitable> >::operator()<boost::asio::detail::write_op<boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>, boost::asio::const_buffer, boost::asio::const_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#1}> >(boost::asio::detail::write_op<boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>, boost::asio::const_buffer, boost::asio::const_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#1}>&&) :118 1x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.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_ASIO_SPAWN_HPP
11 #define BOOST_CAPY_ASIO_SPAWN_HPP
12
13
14 #include <boost/capy/asio/executor_adapter.hpp>
15 #include <boost/capy/asio/detail/completion_traits.hpp>
16 #include <boost/capy/ex/frame_allocator.hpp>
17 #include <boost/capy/concept/execution_context.hpp>
18 #include <boost/capy/concept/executor.hpp>
19 #include <boost/capy/concept/io_awaitable.hpp>
20
21
22 namespace boost::capy
23 {
24
25 /** @addtogroup asio
26 * @{
27 */
28
29 namespace detail
30 {
31
32 /** @brief Helper for initializing spawned coroutines with Boost.Asio tokens.
33 * @internal
34 *
35 * Specialized in `boost.hpp` for actual Boost.Asio completion tokens.
36 */
37 template<typename Awaitable, typename Token>
38 struct initialize_asio_spawn_helper;
39
40 /** @brief Concept for valid Boost.Asio spawn completion tokens.
41 * @internal
42 *
43 * A token satisfies this concept if `initialize_asio_spawn_helper` can
44 * initialize the spawn operation with it.
45 */
46 template<typename Token, typename Executor, typename Awaitable>
47 concept asio_spawn_token =
48 requires (Token && tk, Executor ex, Awaitable rn)
49 {
50 initialize_asio_spawn_helper<Awaitable, Token>::
51 init(std::move(ex), std::move(rn), std::forward<Token>(tk));
52 };
53
54 /** @brief Helper for initializing spawned coroutines with standalone Asio tokens.
55 * @internal
56 *
57 * Specialized in `standalone.hpp` for actual standalone Asio completion tokens.
58 */
59 template<typename Awaitable, typename Token>
60 struct initialize_asio_standalone_spawn_helper;
61
62 /** @brief Concept for valid standalone Asio spawn completion tokens.
63 * @internal
64 *
65 * A token satisfies this concept if `initialize_asio_standalone_spawn_helper`
66 * can initialize the spawn operation with it.
67 */
68 template<typename Token, typename Executor, typename Awaitable>
69 concept asio_standalone_spawn_token =
70 requires (Token && tk, Executor ex, Awaitable rn)
71 {
72 initialize_asio_standalone_spawn_helper<Awaitable, Token>::
73 init(std::move(ex), std::move(rn), std::forward<Token>(tk));
74 };
75
76
77 }
78
79 /** @brief Deferred spawn operation that can be initiated with a completion token.
80 *
81 * This class represents a spawn operation that has captured an executor and
82 * awaitable but hasn't been initiated yet. Call `operator()` with a completion
83 * token to start the operation.
84 *
85 * @tparam Executor The executor type for running the coroutine
86 * @tparam Awaitable The coroutine type (must satisfy `IoAwaitable`)
87 *
88 * @par Example
89 * @code
90 * auto op = asio_spawn(executor, my_coroutine());
91 *
92 * // Initiate with different tokens:
93 * op(asio::detached); // Fire and forget
94 * op([](std::exception_ptr) { ... }); // Callback on completion
95 * co_await op(asio::use_awaitable); // Await in another coroutine
96 * @endcode
97 *
98 * @see asio_spawn Factory function to create spawn operations
99 */
100 template<Executor Executor, IoAwaitable Awaitable>
101 struct asio_spawn_op
102 {
103 /** @brief Constructs the spawn operation.
104 * @param executor The executor to run on
105 * @param awaitable The coroutine to spawn
106 */
107 4x asio_spawn_op(Executor executor, Awaitable awaitable)
108 4x : executor_(std::move(executor)), awaitable_(std::move(awaitable))
109 4x {}
110
111 /** @brief Initiates the spawn with a Boost.Asio completion token.
112 *
113 * @tparam Token A valid Boost.Asio completion token
114 * @param token The completion token determining how to handle completion
115 * @return Depends on the token (e.g., void for callbacks, awaitable for use_awaitable)
116 */
117 template<detail::asio_spawn_token<Executor, Awaitable> Token>
118 4x auto operator()(Token && token)
119 {
120 6x return detail::initialize_asio_spawn_helper<Awaitable, Token>::init(
121 4x std::move(executor_),
122 4x std::move(awaitable_),
123 std::forward<Token>(token)
124 6x );
125 }
126
127 /** @brief Initiates the spawn with a standalone Asio completion token.
128 *
129 * @tparam Token A valid standalone Asio completion token
130 * @param token The completion token determining how to handle completion
131 * @return Depends on the token
132 */
133 template<detail::asio_standalone_spawn_token<Executor, Awaitable> Token>
134 auto operator()(Token && token)
135 {
136 return detail::initialize_asio_standalone_spawn_helper<Awaitable, Token>::init
137 (
138 std::move(executor_),
139 std::move(awaitable_),
140 std::forward<Token>(token)
141 );
142 }
143
144 private:
145 Executor executor_;
146 Awaitable awaitable_;
147 };
148
149
150 /** @brief Spawns a capy coroutine for execution with an Asio completion token.
151 *
152 * Creates a deferred spawn operation that can be initiated with any Asio
153 * completion token. The coroutine will run on the specified executor.
154 *
155 * @tparam ExecutorType The executor type (must satisfy `Executor`)
156 * @tparam Awaitable The coroutine type (must satisfy `IoAwaitable`)
157 * @param exec The executor to run the coroutine on
158 * @param awaitable The coroutine to spawn
159 * @return An `asio_spawn_op` that can be called with a completion token
160 *
161 * @par Completion Signature
162 * The completion signature depends on the coroutine's return type:
163 * - `void` return, noexcept: `void()`
164 * - `void` return, may throw: `void(std::exception_ptr)`
165 * - `T` return, noexcept: `void(T)`
166 * - `T` return, may throw: `void(std::exception_ptr, T)`
167 *
168 * @par Example
169 * @code
170 * capy::task<int> compute() { co_return 42; }
171 *
172 * // Using with Boost.Asio
173 * asio_spawn(executor, compute())(
174 * [](std::exception_ptr ep, int result) {
175 * if (!ep) std::cout << "Result: " << result << "\n";
176 * });
177 *
178 * // Using with asio::use_awaitable
179 * auto [ep, result] = co_await asio_spawn(executor, compute())(asio::use_awaitable);
180 * @endcode
181 *
182 * @see asio_spawn_op The returned operation type
183 */
184 template<Executor ExecutorType, IoAwaitable Awaitable>
185 4x auto asio_spawn(ExecutorType exec, Awaitable && awaitable)
186 {
187 4x return asio_spawn_op(std::move(exec), std::forward<Awaitable>(awaitable));
188 }
189
190 /** @brief Spawns a capy coroutine using a context's executor.
191 *
192 * Convenience overload that extracts the executor from an execution context.
193 *
194 * @tparam Context The execution context type (must satisfy `ExecutionContext`)
195 * @tparam Awaitable The coroutine type (must satisfy `IoAwaitable`)
196 * @param ctx The execution context providing the executor
197 * @param awaitable The coroutine to spawn
198 * @return An `asio_spawn_op` that can be called with a completion token
199 *
200 * @par Example
201 * @code
202 * boost::asio::io_context io;
203 * asio_spawn(io, my_coroutine())(asio::detached);
204 * io.run();
205 * @endcode
206 */
207 template<ExecutionContext Context, IoAwaitable Awaitable>
208 auto asio_spawn(Context & ctx, Awaitable && awaitable)
209 {
210 return asio_spawn_op(ctx.get_executor(), std::forward<Awaitable>(awaitable));
211 }
212
213 /** @} */ // end of asio group
214
215 }
216
217 #endif
218