-
Notifications
You must be signed in to change notification settings - Fork 501
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.