How are you supposed to handle a spurious wakeup of a Parker?

Viewed 300

According to the crossbeam::Parker documentation:

The park method blocks the current thread unless or until the token is available, at which point it automatically consumes the token. It may also return spuriously, without consuming the token.

How are you supposed to detect that a spurious wakeup occurred? Internally, it appears that the parker uses an atomic to track if the token has been consumed or not, but aside from the park and park_timeout methods, there doesn't seem to be a way to query its status.

2 Answers

You are supposed to handle it in some other manner. For example, if you are implementing an mpsc channel manually, your recv function might look something like this:

loop {
    if let Some(message) = self.try_recv() {
        return message;
    }
    park();
}

In this case, if a spurious wake-up happen, the loop will try to obtain the thing it is waiting for again, but since it was a spurious wake-up, the thing is not available, and the loop just goes to sleep again. Once a send actually happens, the sender will unpark the receiver, at which point the try_recv will succeed.

An example of such a channel implementation is available here (source), although it uses a CondVar instead of parking the thread, but it is the same idea.

This has been acknowledged as an issue on the relevant GitHub, and a pull request has been filed to fix it. Once that pull request is merged and released, I'll update this answer with the version that fixes the issue and mark this question as resolved.

Related