@@ -257,14 +257,18 @@ struct join_awaitable {
257257 constexpr auto await_ready (this join_awaitable self) noexcept -> bool {
258258
259259 if (not_null (self.frame )->steals == 0 ) [[likely]] {
260- // If no steals then we are the only owner of the parent and we are ready
261- // to join. Therefore, no need to reset the control block.
260+ // If no steals then we are the only owner of the parent and we are
261+ // ready to join. Therefore, no need to reset the control block.
262+ if (self.frame ->is_cancelled ()) [[unlikely]] {
263+ // Must unconditionally suspended if cancelled
264+ return false ;
265+ }
262266 return true ;
263267 }
264268
265269 // TODO: benchmark if including the below check (returning false here) in
266270 // multithreaded case helps performance enough to justify the extra
267- // instructions along the fast path
271+ // instructions along the fast path and complexity
268272
269273 // Currently: joins() = k_u16_max - num_joined
270274 // Hence: k_u16_max - joins() = num_joined
@@ -281,22 +285,25 @@ struct join_awaitable {
281285 // We must reset the control block and take the stack. We should never
282286 // own the stack at this point because we must have stolen the stack.
283287 // For ruther explanation see await_suspend() below.
284- return self.take_stack_and_reset (), true ;
285- }
288+ self.take_stack_and_reset ();
286289
290+ if (self.frame ->is_cancelled ()) [[unlikely]] {
291+ return false ;
292+ }
293+ return true ;
294+ }
287295 return false ;
288296 }
289297
290298 constexpr auto await_suspend (this join_awaitable self, std::coroutine_handle<> task) noexcept -> coro<> {
291299 // Currently self.joins = k_u16_max - num_joined
300+ //
292301 // We set joins = self->joins - (k_u16_max - num_steals)
293302 // = num_steals - num_joined
294-
303+ //
295304 // Hence joined = k_u16_max - num_joined
296305 // k_u16_max - joined = num_joined
297306
298- LF_ASSUME (self.frame );
299-
300307 // Lemma:
301308 //
302309 // If a thread is at a join and steals have occurred then the
@@ -319,7 +326,14 @@ struct join_awaitable {
319326
320327 // We must reset the control block and take the stack. We should never
321328 // own the stack at this point because we must have stolen the stack.
322- return self.take_stack_and_reset (), task;
329+ self.take_stack_and_reset ();
330+
331+ if (self.frame ->is_cancelled ()) [[unlikely]] {
332+ // TODO: this needs to sink the exception
333+ return std::noop_coroutine ();
334+ }
335+
336+ return task;
323337 }
324338
325339 // Someone else is responsible for running this task.
@@ -332,6 +346,7 @@ struct join_awaitable {
332346 // in a switch awaitable. In this case we can/must do another self-steal.
333347
334348 // return try_self_stealing();
349+
335350 return std::noop_coroutine ();
336351 }
337352
0 commit comments