@@ -312,14 +312,18 @@ struct join_awaitable {
312312 constexpr auto await_ready (this join_awaitable self) noexcept -> bool {
313313
314314 if (not_null (self.frame )->steals == 0 ) [[likely]] {
315- // If no steals then we are the only owner of the parent and we are ready
316- // to join. Therefore, no need to reset the control block.
315+ // If no steals then we are the only owner of the parent and we are
316+ // ready to join. Therefore, no need to reset the control block.
317+ if (self.frame ->is_cancelled ()) [[unlikely]] {
318+ // Must unconditionally suspended if cancelled
319+ return false ;
320+ }
317321 return true ;
318322 }
319323
320324 // TODO: benchmark if including the below check (returning false here) in
321325 // multithreaded case helps performance enough to justify the extra
322- // instructions along the fast path
326+ // instructions along the fast path and complexity
323327
324328 // Currently: joins() = k_u16_max - num_joined
325329 // Hence: k_u16_max - joins() = num_joined
@@ -336,22 +340,25 @@ struct join_awaitable {
336340 // We must reset the control block and take the stack. We should never
337341 // own the stack at this point because we must have stolen the stack.
338342 // For ruther explanation see await_suspend() below.
339- return self.take_stack_and_reset (), true ;
340- }
343+ self.take_stack_and_reset ();
341344
345+ if (self.frame ->is_cancelled ()) [[unlikely]] {
346+ return false ;
347+ }
348+ return true ;
349+ }
342350 return false ;
343351 }
344352
345353 constexpr auto await_suspend (this join_awaitable self, std::coroutine_handle<> task) noexcept -> coro<> {
346354 // Currently self.joins = k_u16_max - num_joined
355+ //
347356 // We set joins = self->joins - (k_u16_max - num_steals)
348357 // = num_steals - num_joined
349-
358+ //
350359 // Hence joined = k_u16_max - num_joined
351360 // k_u16_max - joined = num_joined
352361
353- LF_ASSUME (self.frame );
354-
355362 // Lemma:
356363 //
357364 // If a thread is at a join and steals have occurred then the
@@ -374,7 +381,14 @@ struct join_awaitable {
374381
375382 // We must reset the control block and take the stack. We should never
376383 // own the stack at this point because we must have stolen the stack.
377- return self.take_stack_and_reset (), task;
384+ self.take_stack_and_reset ();
385+
386+ if (self.frame ->is_cancelled ()) [[unlikely]] {
387+ // TODO: this needs to sink the exception
388+ return std::noop_coroutine ();
389+ }
390+
391+ return task;
378392 }
379393
380394 // Someone else is responsible for running this task.
@@ -387,6 +401,7 @@ struct join_awaitable {
387401 // in a switch awaitable. In this case we can/must do another self-steal.
388402
389403 // return try_self_stealing();
404+
390405 return std::noop_coroutine ();
391406 }
392407
0 commit comments