#![cfg_attr(not(feature = "libc"), no_std)]
#![cfg_attr(feature = "doc_cfg", feature(doc_cfg))]
#![deny(unsafe_op_in_unsafe_fn)]
#[allow(unused_imports)]
use core::sync::atomic;
#[cfg(not(feature = "libc"))]
use core::ffi;
#[cfg(feature = "libc")]
use libc as ffi;
#[allow(unused_imports)]
use ffi as _;
mod detail {
pub trait GetAtomicOrFallback {
type Type;
}
pub struct AtomicOrFallback<T, Fallback, const HAS_ATOMIC: bool>(
core::marker::PhantomData<fn() -> (T, Fallback)>,
);
impl<T, Fallback> GetAtomicOrFallback
for AtomicOrFallback<T, Fallback, false>
{
type Type = Fallback;
}
}
#[allow(dead_code)]
use detail::{AtomicOrFallback, GetAtomicOrFallback};
#[allow(dead_code)]
struct AtomicMeta<T>(core::marker::PhantomData<fn() -> T>);
#[allow(dead_code)]
trait DefaultAtomicMeta {
const HAS_ATOMIC: bool = false;
}
impl<T> DefaultAtomicMeta for AtomicMeta<T> {}
macro_rules! with_primitive_atomics {
($macro:path) => {
$macro!(AtomicI8, i8, [target_has_atomic = "8"], "");
$macro!(AtomicU8, u8, [target_has_atomic = "8"], "");
$macro!(AtomicI16, i16, [target_has_atomic = "16"], "");
$macro!(AtomicU16, u16, [target_has_atomic = "16"], "");
$macro!(AtomicI32, i32, [target_has_atomic = "32"], "");
$macro!(AtomicU32, u32, [target_has_atomic = "32"], "");
$macro!(AtomicI64, i64, [target_has_atomic = "64"], "");
$macro!(AtomicU64, u64, [target_has_atomic = "64"], "");
$macro!(
AtomicI128,
i128,
[any()],
"**Note:** Because 128-bit atomics are unstable, this type is \
always a spinlock-based fallback. This may change in a future \
version of this crate."
);
$macro!(
AtomicU128,
u128,
[any()],
"**Note:** Because 128-bit atomics are unstable, this type is \
always a spinlock-based fallback. This may change in a future \
version of this crate."
);
$macro!(AtomicIsize, isize, [target_has_atomic = "ptr"], "");
$macro!(AtomicUsize, usize, [target_has_atomic = "ptr"], "");
};
}
macro_rules! impl_atomic_meta {
($atomic:ident, $int:ident, [$($cfg:tt)*], $($x:tt)*) => {
#[cfg(all(not(feature = "force-fallback"), $($cfg)*))]
#[allow(dead_code)]
impl AtomicMeta<$int> {
pub const HAS_ATOMIC: bool = true;
}
#[cfg(all(not(feature = "force-fallback"), $($cfg)*))]
impl<Fallback> GetAtomicOrFallback
for AtomicOrFallback<$int, Fallback, true>
{
type Type = atomic::$atomic;
}
};
}
with_primitive_atomics!(impl_atomic_meta);
#[allow(unused_macros)]
macro_rules! define_primitive_atomic {
(
$atomic:ident$(<$generic:ident>)?,
$type:ty,
[$($cfg:tt)*],
$doc:expr
) => {
#[cfg(all(not(doc), not(feature = "force-fallback"), $($cfg)*))]
pub type $atomic$(<$generic>)? = atomic::$atomic$(<$generic>)?;
#[cfg(any(doc, feature = "force-fallback", not($($cfg)*)))]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "primitives")))]
#[doc = concat!("[`", stringify!($type), "`].")]
#[doc = $doc]
pub type $atomic$(<$generic>)? = fallback::$atomic$(<$generic>)?;
};
}
#[cfg(feature = "primitives")]
with_primitive_atomics!(define_primitive_atomic);
#[cfg(feature = "primitives")]
define_primitive_atomic!(
AtomicPtr<T>,
*mut T,
[target_has_atomic = "ptr"],
"[`*mut T`]: pointer"
);
#[cfg(feature = "primitives")]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "primitives")))]
pub type AtomicBool = atomic::AtomicBool;
macro_rules! with_c_atomics {
($macro:path) => {
#[cfg(feature = "c_char")]
$macro!(AtomicCChar, c_char, "c_char");
#[cfg(feature = "c_schar")]
$macro!(AtomicCSchar, c_schar, "c_schar");
#[cfg(feature = "c_uchar")]
$macro!(AtomicCUchar, c_uchar, "c_uchar");
#[cfg(feature = "c_short")]
$macro!(AtomicCShort, c_short, "c_short");
#[cfg(feature = "c_ushort")]
$macro!(AtomicCUshort, c_ushort, "c_ushort");
#[cfg(feature = "c_int")]
$macro!(AtomicCInt, c_int, "c_int");
#[cfg(feature = "c_uint")]
$macro!(AtomicCUint, c_uint, "c_uint");
#[cfg(feature = "c_long")]
$macro!(AtomicCLong, c_long, "c_long");
#[cfg(feature = "c_ulong")]
$macro!(AtomicCUlong, c_ulong, "c_ulong");
#[cfg(feature = "c_longlong")]
$macro!(AtomicCLonglong, c_longlong, "c_longlong");
#[cfg(feature = "c_ulonglong")]
$macro!(AtomicCUlonglong, c_ulonglong, "c_ulonglong");
};
}
#[allow(unused_macros)]
macro_rules! alias_c_type {
($atomic:ident, $int:ident, $($x:tt)*) => {
#[allow(clippy::incompatible_msrv)] #[allow(non_camel_case_types)]
pub type $int = super::ffi::$int;
};
}
mod c_types {
with_c_atomics!(alias_c_type);
}
#[allow(unused_macros)]
macro_rules! define_c_atomic {
($atomic:ident, $int:ident, $feature:literal) => {
#[cfg(not(doc))]
pub type $atomic = <AtomicOrFallback<
c_types::$int,
fallback::$atomic,
{ AtomicMeta::<c_types::$int>::HAS_ATOMIC },
> as GetAtomicOrFallback>::Type;
#[cfg(doc)]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = $feature)))]
#[doc = concat!("[`", stringify!($int), "`][1].")]
#[doc = concat!("[1]: ffi::", stringify!($int))]
pub type $atomic = fallback::$atomic;
};
}
with_c_atomics!(define_c_atomic);
mod fallback;
#[cfg(doc)]
#[cfg_attr(feature = "doc_cfg", doc(cfg(doc)))]
pub use fallback::AtomicFallback;
#[cfg(doc)]
#[cfg_attr(feature = "doc_cfg", doc(cfg(doc)))]
pub use fallback::AtomicFallbackPtr;