Expand description
Futex-based wakeups for crossbeam_channel channels.
When throughput is high and perf matters the most, this code is basically zero cost. When
throughput is low, the futex based protocol described below kicks in, which is much more
performant than crossbeam’s SyncWaker (which, among other things, uses a mutex contended at
every wake up by all senders and receivers).
§Synchronization protocol
Receivers sleep waiting for new messages when a channel is empty. After the underlying channel’s
try_recv() returns Empty, a receiver registers a waiter and calls try_recv() again before
sleeping. If the channel is not empty anymore, the receiver returns the message immediately. If
the channel is still empty, the receiver sleeps until a sender wakes it up.
When a sender sends a message, it enqueues it into the channel and calls wake_one(). If no
receivers are sleeping, wake_one() does nothing. If any receivers are sleeping, one is woken
up so it can process the message.
The fences in register_waiter() and wake_*() allow the “wake_one() does nothing”
optimization, guaranteeing that either a receiver’s second try_recv() observes a message, or
the sender observes the registered waiter and so can wake it.
Structs§
- Receiver
- Wrapper around
crossbeam_channel::Receiverthat avoids contention by using a futex to sleep waiting for messages when the channel is empty. - Sender
- Wrapper around
crossbeam_channel::Senderthat avoids contention by using a futex to wake sleeping receivers when a message is sent.