-
Notifications
You must be signed in to change notification settings - Fork 516
Description
It would be convenient if I could check if AtomicCells are lock-free at compile time. by marking AtomicCell<T>::is_lock_free() as a const fn.
For context, I'm working on an audio program in C++, due to C++ libraries including Qt. In audio programs, taking locks on the audio thread is regarded as unacceptable because it can block and cause the audio to stutter. As a result, I'd like to statically assert that a given atomic type written by the audio thread is lock-free. (I'm mostly looking at Rust for inspiration and comparison, to see whether parts of my code are nicer in C++ or Rust.)
crossbeam/crossbeam-utils/src/atomic/atomic_cell.rs
Lines 108 to 110 in 81ab18e
| pub fn is_lock_free() -> bool { | |
| atomic_is_lock_free::<T>() | |
| } |
calls atomic_is_lock_free<T>:
crossbeam/crossbeam-utils/src/atomic/atomic_cell.rs
Lines 809 to 812 in 81ab18e
| /// Returns `true` if operations on `AtomicCell<T>` are lock-free. | |
| fn atomic_is_lock_free<T>() -> bool { | |
| atomic! { T, _a, true, false } | |
| } |
expands to the atomic! macro:
crossbeam/crossbeam-utils/src/atomic/atomic_cell.rs
Lines 777 to 807 in 81ab18e
| macro_rules! atomic { | |
| // If values of type `$t` can be transmuted into values of the primitive atomic type `$atomic`, | |
| // declares variable `$a` of type `$atomic` and executes `$atomic_op`, breaking out of the loop. | |
| (@check, $t:ty, $atomic:ty, $a:ident, $atomic_op:expr) => { | |
| if can_transmute::<$t, $atomic>() { | |
| let $a: &$atomic; | |
| break $atomic_op; | |
| } | |
| }; | |
| // If values of type `$t` can be transmuted into values of a primitive atomic type, declares | |
| // variable `$a` of that type and executes `$atomic_op`. Otherwise, just executes | |
| // `$fallback_op`. | |
| ($t:ty, $a:ident, $atomic_op:expr, $fallback_op:expr) => { | |
| loop { | |
| atomic!(@check, $t, AtomicUnit, $a, $atomic_op); | |
| atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op); | |
| #[cfg(has_atomic_u8)] | |
| atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op); | |
| #[cfg(has_atomic_u16)] | |
| atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op); | |
| #[cfg(has_atomic_u32)] | |
| atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op); | |
| #[cfg(has_atomic_u64)] | |
| atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op); | |
| break $fallback_op; | |
| } | |
| }; | |
| } |
Marking AtomicCell<T>::is_lock_free() as const doesn't seem to cause issues, but depends on atomic_is_lock_free. Trying to mark atomic_is_lock_free as const fails on rust-lang/rust#49146 "Allow if and match in constants", and rust-lang/rust#52000 "Allow loop in constant evaluation".
From a cursory examination, atomic! doesn't truly need a loop, but depends on if. Note that I don't fully understand atomic! nor all call sites.
Are there any plans to mark this as a const fn, to allow users to statically assert it's lock-free? I don't know if atomic! needs to be split into two macros or not, with duplication and possible future desynchronization.