@@ -33,10 +33,21 @@ namespace lf::impl {
33
33
34
34
// -------------------------------------------------------- //
35
35
36
+ /* *
37
+ * @brief An awaiter to explicitly transfer execution to another worker.
38
+ *
39
+ * This is generated by `await_transform` when awaiting on a pointer to a `lf::context`.
40
+ */
36
41
struct switch_awaitable : std::suspend_always {
37
42
43
+ /* *
44
+ * @brief Shortcut if already on context.
45
+ */
38
46
auto await_ready () const noexcept { return tls::context () == dest; }
39
47
48
+ /* *
49
+ * @brief Reschedule this coro onto `dest`.
50
+ */
40
51
auto await_suspend (std::coroutine_handle<>) noexcept -> std::coroutine_handle<> {
41
52
42
53
// Schedule this coro for execution on Dest.
@@ -71,14 +82,23 @@ struct switch_awaitable : std::suspend_always {
71
82
return std::noop_coroutine ();
72
83
}
73
84
74
- intrusive_list<submit_handle>::node self;
75
- context *dest;
85
+ intrusive_list<submit_handle>::node self; // /< The current coroutine's handle.
86
+ context *dest; // /< Target context.
76
87
};
77
88
78
89
// -------------------------------------------------------- //
79
90
91
+ /* *
92
+ * @brief An awaiter that returns space allocated on the current fibre's stack.
93
+ *
94
+ * This never suspends the coroutine and is generated by `await_transform` when awaiting on a pointer to a
95
+ * `lf::context`.
96
+ */
80
97
template <typename T, std::size_t E>
81
98
struct alloc_awaitable : std::suspend_never, std::span<T, E> {
99
+ /* *
100
+ * @brief Return a handle to the memory.
101
+ */
82
102
[[nodiscard]] auto await_resume () const noexcept -> std::conditional_t<E == 1, T *, std::span<T, E>> {
83
103
if constexpr (E == 1 ) {
84
104
return this ->data ();
@@ -90,8 +110,16 @@ struct alloc_awaitable : std::suspend_never, std::span<T, E> {
90
110
91
111
// -------------------------------------------------------- //
92
112
113
+ /* *
114
+ * @brief An awaiter that suspends the current coroutine and transfers control to a child task.
115
+ *
116
+ * The parent task is made available for stealing. This is generated by `await_transform` when awaiting on an
117
+ * `lf::impl::quasi_awaitable`.
118
+ */
93
119
struct fork_awaitable : std::suspend_always {
94
-
120
+ /* *
121
+ * @brief Sym-transfer to child, push parent to queue.
122
+ */
95
123
auto await_suspend (std::coroutine_handle<>) const noexcept -> std::coroutine_handle<> {
96
124
LF_LOG (" Forking, push parent to context" );
97
125
// Need a copy (on stack) in case *this is destructed after push.
@@ -100,22 +128,35 @@ struct fork_awaitable : std::suspend_always {
100
128
return child;
101
129
}
102
130
103
- frame *child;
104
- frame *parent;
131
+ frame *child; // /< The suspended child coroutine's frame.
132
+ frame *parent; // /< The calling coroutine's frame.
105
133
};
106
134
135
+ /* *
136
+ * @brief An awaiter that suspends the current coroutine and transfers control to a child task.
137
+ *
138
+ * The parent task is __not__ made available for stealing. This is generated by `await_transform` when
139
+ * awaiting on an `lf::impl::quasi_awaitable`.
140
+ */
107
141
struct call_awaitable : std::suspend_always {
108
-
142
+ /* *
143
+ * @brief Sym-transfer to child.
144
+ */
109
145
auto await_suspend (std::coroutine_handle<>) const noexcept -> std::coroutine_handle<> {
110
146
LF_LOG (" Calling" );
111
147
return child->self ();
112
148
}
113
149
114
- frame *child;
150
+ frame *child; // /< The suspended child coroutine's frame.
115
151
};
116
152
117
153
// -------------------------------------------------------------------------------- //
118
154
155
+ /* *
156
+ * @brief An awaiter to synchronize execution of child tasks.
157
+ *
158
+ * This is generated by `await_transform` when awaiting on an `lf::impl::join_type`.
159
+ */
119
160
struct join_awaitable {
120
161
private:
121
162
void take_stack_reset_frame () const noexcept {
@@ -128,6 +169,9 @@ struct join_awaitable {
128
169
}
129
170
130
171
public:
172
+ /* *
173
+ * @brief Shortcut if children are ready.
174
+ */
131
175
auto await_ready () const noexcept -> bool {
132
176
// If no steals then we are the only owner of the parent and we are ready to join.
133
177
if (self->load_steals () == 0 ) {
@@ -154,6 +198,9 @@ struct join_awaitable {
154
198
return false ;
155
199
}
156
200
201
+ /* *
202
+ * @brief Mark at join point then yield to scheduler or resume if children are done.
203
+ */
157
204
auto await_suspend (std::coroutine_handle<> task) const noexcept -> std::coroutine_handle<> {
158
205
// Currently joins = k_u16_max - num_joined
159
206
// We set joins = joins() - (k_u16_max - num_steals)
@@ -188,6 +235,9 @@ struct join_awaitable {
188
235
return std::noop_coroutine ();
189
236
}
190
237
238
+ /* *
239
+ * @brief A noop in release.
240
+ */
191
241
void await_resume () const noexcept {
192
242
LF_LOG (" join resumes" );
193
243
// Check we have been reset.
@@ -196,7 +246,7 @@ struct join_awaitable {
196
246
LF_ASSERT (self->stacklet () == tls::stack ()->top ());
197
247
}
198
248
199
- frame *self;
249
+ frame *self; // /< The frame of the awaiting coroutine.
200
250
};
201
251
202
252
} // namespace lf::impl
0 commit comments