Skip to content

Mark AtomicCell::is_lock_free() as const fn? #531

@nyanpasu64

Description

@nyanpasu64

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.)

pub fn is_lock_free() -> bool {
atomic_is_lock_free::<T>()
}

calls atomic_is_lock_free<T>:

/// 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:

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions