valet_parking
provides the service of parking your threads.
This library provides a cross-platform abstraction for thread parking which only needs one AtomicUsize
to operate on, and is no_std
-compatible.
Two patterns:
Waiters
: multiple threads can wait on a singleAtomicUsize
until one thread wakes them all up at once.Parker
: One thread parkes itself, and multiple threads or a timeout are able to wake it up.
valet
has two primary goals:
- Offer a cross-platform abstraction for thread parking.
- Be usable in other libraries that offer
no_std
support, even withoutalloc
.
Some systems provide a way to park a thread while requiring nothing more than a single atomic. Other systems need multiple variables. The generic Posix implementation is such an example, it requires a condvar with mutex. valet
is able to offer an API that requires only an AtomicUsize
thanks to one key observation: we can use the stack of a parked thread to store the extra fields.
This does however takes some extra care on the side of valet
to ensure no thread does reads from the stack of a thread while it is getting unparked.
OS | interface | max. timeout | notes |
---|---|---|---|
Linux, Android | futex¹ ² | ≥ 2^31 s | |
Windows 8+ | WaitOnAddress³ | 2^63 ×100ns | |
Windows XP+ | NT Keyed Events⁴ ⁵ | 2^32 ms | we keep a count of the waiting threads |
FreeBSD | umutex⁶ | 2^63 s | |
OpenBSD | futex⁷ | 2^63 s | |
Posix-compatible | condition variable⁸ | ≥ 2^31 s | we keep a queue of waiting threads |
Generic fallback | spin loop | not supported | (WIP) |
Fuchsia OS | futex⁹ | 2^63 s | (untested) |
Redox | futex¹⁰ | 2^63 s | (untested) |
Fortanix SGX | wait¹² | not supported | (WIP), we keep a queue of waiting threads (requires std) |
WASM atomics | i32.atomic.wait¹³ | 2^63 ns | (untested) |
MacOS 10.12+, iOS 10.0+ | ulock | 2^32 μs | |
DragonFly BSD | userland mutex¹⁴ | 2^31 μs | |
illumos | futex | ... | (WIP) rust-lang/rust#55553 |
Haiku | benaphore | ... | (WIP) https://github.com/nielx/haiku-rs |
The goal to provide an API that can be used without allocations has a big impact on the design of valet
. Take the generic Posix implementation as an example. It requires a condvar with a mutex for thread parking. If valet
were to provide some ThreadParker
type containing fields for these two, you would have to store it in some place in memory that is accessable to both threads. This would typically be an Arc
, or some other structure requring an allocation.
Instead valet
provides an API that only requires you to pass around a reference to an AtomicUsize
.
In the case were multiple variables are required
The current minimum required Rust version is 1.33.
Licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.