2020namespace boost {
2121namespace capy {
2222
23- /* * Callable that posts a continuation to an executor.
24-
25- Use this as the callback type for `std::stop_callback` instead
26- of resuming a coroutine handle directly. Direct resumption runs
27- the coroutine inline on whatever thread calls `request_stop()`,
28- which bypasses the executor and corrupts the thread-local
29- frame allocator.
30-
31- Prefer @ref io_env::post_resume and the @ref stop_resume_callback
32- alias to construct these—see examples there.
33-
34- @see io_env::post_resume, stop_resume_callback
35- */
36- struct resume_via_post
37- {
38- executor_ref ex;
39- mutable continuation cont;
40-
41- // post() must not throw; stop_callback requires a
42- // non-throwing invocable.
43- void operator ()() const noexcept
44- {
45- ex.post (cont);
46- }
47- };
48-
4923/* * Execution environment for IoAwaitables.
5024
5125 This struct bundles the execution context passed through
@@ -60,27 +34,11 @@ struct resume_via_post
6034 chain. Awaitables receive `io_env const*` in `await_suspend`
6135 and should store it directly, never copy the pointed-to object.
6236
63- @par Stop Callback Contract
64-
65- Awaitables that register a `std::stop_callback` **must not**
66- resume the coroutine handle directly. The callback fires
67- synchronously on the thread that calls `request_stop()`, which
68- may not be an executor-managed thread. Resuming inline poisons
69- that thread's TLS frame allocator with the pool's allocator,
70- causing use-after-free on the next coroutine allocation.
71-
72- Use @ref io_env::post_resume and @ref stop_resume_callback:
73- @code
74- std::optional<stop_resume_callback> stop_cb_;
75- // In await_suspend:
76- stop_cb_.emplace(env->stop_token, env->post_resume(h));
77- @endcode
78-
7937 @par Thread Safety
8038 The referenced executor and allocator must remain valid
8139 for the lifetime of any coroutine using this environment.
8240
83- @see IoAwaitable, IoRunnable, resume_via_post
41+ @see IoAwaitable, IoRunnable
8442*/
8543struct io_env
8644{
@@ -96,45 +54,8 @@ struct io_env
9654 */
9755 std::pmr::memory_resource* frame_allocator = nullptr ;
9856
99- /* * Create a resume_via_post callable for this environment.
100-
101- Convenience method for registering @ref stop_resume_callback
102- instances. Wraps the coroutine handle in a @ref continuation
103- and pairs it with this environment's executor. Equivalent to
104- `resume_via_post{executor, continuation{h}}`.
105-
106- @par Example
107- @code
108- stop_cb_.emplace(env->stop_token, env->post_resume(h));
109- @endcode
110-
111- @param h The coroutine handle to wrap in a continuation
112- and post on cancellation.
113-
114- @return A @ref resume_via_post callable that holds a
115- non-owning @ref executor_ref and a @ref continuation.
116- The callable must not outlive the executor it references.
117-
118- @see resume_via_post, stop_resume_callback
119- */
120- resume_via_post
121- post_resume (std::coroutine_handle<> h) const noexcept
122- {
123- return resume_via_post{executor, continuation{h}};
124- }
12557};
12658
127- /* * Type alias for a stop callback that posts through the executor.
128-
129- Use this to declare the stop callback member in your awaitable:
130- @code
131- std::optional<stop_resume_callback> stop_cb_;
132- @endcode
133-
134- @see resume_via_post, io_env::post_resume
135- */
136- using stop_resume_callback = std::stop_callback<resume_via_post>;
137-
13859} // capy
13960} // boost
14061
0 commit comments