Clarification needed on UnsafeContinuation documentation

I find the meaning of the documentation hard to understand.

Consider the following code (which I'm using in unit tests to synchronize progress of two tasks). Depending on the interpretation of the documentation there is a race condition in self.completion = $0.

actor MeetingPoint {
    var completion: CheckedContinuation<Void, Never>? = nil

    func join() async {
        if let completion = completion {
            self.completion = nil
            completion.resume()
        } else {
            await withCheckedContinuation {
                self.completion = $0
            }
        }
    }
}

When two tasks call join at the same time, one will succeed and enter the actor. This task progresses to await withCheckedContinuation. If the task suspends at this point, before calling the closure, the second task may enter the actor and find the condition in the wrong state (completion == nil). That's not the intended behavior.

If, on the other hand, the task does not suspend before the closure is executed, the behavior is as intended and there's no race condition.

The documentation makes me think the code is wrong, and checking needs to take place within the closure.

2 Likes