utils_atomics/
lib.rs

1#![deny(clippy::all)]
2#![deny(clippy::perf)]
3#![warn(clippy::pedantic)]
4#![allow(clippy::needless_return)]
5#![allow(clippy::missing_safety_doc)]
6#![allow(clippy::must_use_candidate)]
7#![allow(clippy::semicolon_if_nothing_returned)]
8#![allow(clippy::module_name_repetitions)]
9#![allow(clippy::wildcard_imports)]
10#![allow(clippy::explicit_deref_methods)]
11#![allow(clippy::match_bool)]
12#![cfg_attr(test, allow(clippy::bool_assert_comparison))]
13/* */
14#![cfg_attr(feature = "nightly", feature(int_roundings, negative_impls, c_size_t))]
15#![cfg_attr(all(feature = "nightly", feature = "alloc"), feature(new_uninit))]
16#![cfg_attr(not(feature = "std"), no_std)]
17#![cfg_attr(feature = "alloc_api", feature(allocator_api))]
18#![cfg_attr(feature = "const", feature(const_trait_impl))]
19#![cfg_attr(docsrs, feature(doc_cfg))]
20
21use core::fmt::Display;
22
23use docfg::docfg;
24
25#[cfg(feature = "alloc")]
26pub(crate) extern crate alloc;
27
28macro_rules! flat_mod {
29    ($($i:ident),+) => {
30        $(
31            mod $i;
32            pub use $i::*;
33        )+
34    };
35}
36
37cfg_if::cfg_if! {
38    if #[cfg(feature = "alloc_api")] {
39        #[doc(hidden)]
40        pub use core::alloc::AllocError;
41    } else {
42        /// The `AllocError` error indicates an allocation failure
43        /// that may be due to resource exhaustion or to
44        /// something wrong when combining the given input arguments with this
45        /// allocator.
46        #[doc(hidden)]
47        #[derive(Copy, Clone, PartialEq, Eq, Debug)]
48        pub struct AllocError;
49
50        #[cfg(feature = "std")]
51        impl std::error::Error for AllocError {}
52
53        // (we need this for downstream impl of trait Error)
54        impl core::fmt::Display for AllocError {
55            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
56                f.write_str("memory allocation failed")
57            }
58        }
59    }
60}
61
62cfg_if::cfg_if! {
63    if #[cfg(feature = "alloc")] {
64        // #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
65        // pub mod semaphore;
66        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
67        pub mod fill_queue;
68        mod bitfield;
69        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
70        pub mod flag;
71        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
72        pub mod channel;
73        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
74        pub mod notify;
75        mod cell;
76        // #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
77        // pub mod arc_cell;
78        mod locks;
79
80        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
81        pub use bitfield::AtomicBitBox;
82        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
83        pub use cell::AtomicCell;
84        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
85        pub use fill_queue::FillQueue;
86        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
87        pub use locks::*;
88        #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
89        pub use bitfield::*;
90    }
91}
92
93flat_mod!(take);
94
95#[path = "trait.rs"]
96pub mod traits;
97
98pub mod prelude {
99    #[docfg::docfg(feature = "alloc")]
100    pub use crate::fill_queue::*;
101    pub use crate::take::*;
102    pub use crate::traits::Atomic;
103}
104
105cfg_if::cfg_if! {
106    if #[cfg(target_has_atomic = "8")] {
107        pub(crate) type InnerFlag = u8;
108        pub(crate) type InnerAtomicFlag = core::sync::atomic::AtomicU8;
109    } else if #[cfg(target_has_atomic = "16")] {
110        pub(crate) type InnerFlag = u16;
111        pub(crate) type InnerAtomicFlag = core::sync::atomic::AtomicU16;
112    } else if #[cfg(target_has_atomic = "32")] {
113        pub(crate) type InnerFlag = u32;
114        pub(crate) type InnerAtomicFlag = core::sync::atomic::AtomicU32;
115    } else if #[cfg(target_has_atomic = "64")] {
116        pub(crate) type InnerFlag = u64;
117        pub(crate) type InnerAtomicFlag = core::sync::atomic::AtomicU64;
118    } else {
119        pub(crate) type InnerFlag = usize;
120        pub(crate) type InnerAtomicFlag = core::sync::atomic::AtomicUsize;
121    }
122}
123
124pub(crate) const TRUE: InnerFlag = 1;
125pub(crate) const FALSE: InnerFlag = 0;
126
127/// Error returned when a timeout ocurrs before the main operation completes.
128#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
129pub struct Timeout;
130
131impl Display for Timeout {
132    #[inline]
133    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
134        write!(
135            f,
136            "The main operation timed out before it could be completed"
137        )
138    }
139}
140
141#[docfg(feature = "std")]
142impl std::error::Error for Timeout {}
143
144#[allow(unused)]
145#[inline]
146pub(crate) fn is_some_and<T, F: FnOnce(T) -> bool>(v: Option<T>, f: F) -> bool {
147    match v {
148        None => false,
149        Some(x) => f(x),
150    }
151}
152
153#[allow(unused)]
154#[inline]
155pub(crate) fn div_ceil(lhs: usize, rhs: usize) -> usize {
156    cfg_if::cfg_if! {
157        if #[cfg(feature = "nightly")] {
158            return lhs.div_ceil(rhs)
159        } else {
160            let d = lhs / rhs;
161            let r = lhs % rhs;
162            if r > 0 && rhs > 0 {
163                d + 1
164            } else {
165                d
166            }
167        }
168    }
169}