@@ -324,14 +324,18 @@ struct join_awaitable {
324324 constexpr auto await_ready (this join_awaitable self) noexcept -> bool {
325325
326326 if (not_null (self.frame )->steals == 0 ) [[likely]] {
327- // If no steals then we are the only owner of the parent and we are ready
328- // to join. Therefore, no need to reset the control block.
327+ // If no steals then we are the only owner of the parent and we are
328+ // ready to join. Therefore, no need to reset the control block.
329+ if (self.frame ->is_cancelled ()) [[unlikely]] {
330+ // Must unconditionally suspended if cancelled
331+ return false ;
332+ }
329333 return true ;
330334 }
331335
332336 // TODO: benchmark if including the below check (returning false here) in
333337 // multithreaded case helps performance enough to justify the extra
334- // instructions along the fast path
338+ // instructions along the fast path and complexity
335339
336340 // Currently: joins() = k_u16_max - num_joined
337341 // Hence: k_u16_max - joins() = num_joined
@@ -348,22 +352,25 @@ struct join_awaitable {
348352 // We must reset the control block and take the stack. We should never
349353 // own the stack at this point because we must have stolen the stack.
350354 // For ruther explanation see await_suspend() below.
351- return self.take_stack_and_reset (), true ;
352- }
355+ self.take_stack_and_reset ();
353356
357+ if (self.frame ->is_cancelled ()) [[unlikely]] {
358+ return false ;
359+ }
360+ return true ;
361+ }
354362 return false ;
355363 }
356364
357365 constexpr auto await_suspend (this join_awaitable self, std::coroutine_handle<> task) noexcept -> coro<> {
358366 // Currently self.joins = k_u16_max - num_joined
367+ //
359368 // We set joins = self->joins - (k_u16_max - num_steals)
360369 // = num_steals - num_joined
361-
370+ //
362371 // Hence joined = k_u16_max - num_joined
363372 // k_u16_max - joined = num_joined
364373
365- LF_ASSUME (self.frame );
366-
367374 // Lemma:
368375 //
369376 // If a thread is at a join and steals have occurred then the
@@ -386,7 +393,14 @@ struct join_awaitable {
386393
387394 // We must reset the control block and take the stack. We should never
388395 // own the stack at this point because we must have stolen the stack.
389- return self.take_stack_and_reset (), task;
396+ self.take_stack_and_reset ();
397+
398+ if (self.frame ->is_cancelled ()) [[unlikely]] {
399+ // TODO: this needs to sink the exception
400+ return std::noop_coroutine ();
401+ }
402+
403+ return task;
390404 }
391405
392406 // Someone else is responsible for running this task.
@@ -399,6 +413,7 @@ struct join_awaitable {
399413 // in a switch awaitable. In this case we can/must do another self-steal.
400414
401415 // return try_self_stealing();
416+
402417 return std::noop_coroutine ();
403418 }
404419
0 commit comments