concurrent_queue/
sync.rs

1//! Synchronization facade to choose between `core` primitives and `loom` primitives.
2
3#[cfg(all(feature = "portable-atomic", not(loom)))]
4mod sync_impl {
5    pub(crate) use core::cell;
6    pub(crate) use portable_atomic as atomic;
7
8    #[cfg(not(feature = "std"))]
9    pub(crate) use atomic::hint::spin_loop;
10
11    #[cfg(feature = "std")]
12    pub(crate) use std::thread::yield_now;
13}
14
15#[cfg(all(not(feature = "portable-atomic"), not(loom)))]
16mod sync_impl {
17    pub(crate) use core::cell;
18    pub(crate) use core::sync::atomic;
19
20    #[cfg(not(feature = "std"))]
21    #[inline]
22    pub(crate) fn spin_loop() {
23        #[allow(deprecated)]
24        atomic::spin_loop_hint();
25    }
26
27    #[cfg(feature = "std")]
28    pub(crate) use std::thread::yield_now;
29}
30
31#[cfg(loom)]
32mod sync_impl {
33    pub(crate) use loom::cell;
34
35    pub(crate) mod atomic {
36        pub(crate) use loom::sync::atomic::*;
37    }
38
39    #[cfg(not(feature = "std"))]
40    pub(crate) use loom::hint::spin_loop;
41    #[cfg(feature = "std")]
42    pub(crate) use loom::thread::yield_now;
43}
44
45pub(crate) use sync_impl::*;
46
47/// Notify the CPU that we are currently busy-waiting.
48#[inline]
49pub(crate) fn busy_wait() {
50    #[cfg(feature = "std")]
51    yield_now();
52
53    #[cfg(not(feature = "std"))]
54    spin_loop();
55}
56
57#[cfg(loom)]
58pub(crate) mod prelude {}
59
60#[cfg(not(loom))]
61pub(crate) mod prelude {
62    use super::{atomic, cell};
63
64    /// Emulate `loom::UnsafeCell`'s API.
65    pub(crate) trait UnsafeCellExt {
66        type Value;
67
68        fn with_mut<R, F>(&self, f: F) -> R
69        where
70            F: FnOnce(*mut Self::Value) -> R;
71    }
72
73    impl<T> UnsafeCellExt for cell::UnsafeCell<T> {
74        type Value = T;
75
76        fn with_mut<R, F>(&self, f: F) -> R
77        where
78            F: FnOnce(*mut Self::Value) -> R,
79        {
80            f(self.get())
81        }
82    }
83
84    /// Emulate `loom::Atomic*`'s API.
85    pub(crate) trait AtomicExt {
86        type Value;
87
88        fn with_mut<R, F>(&mut self, f: F) -> R
89        where
90            F: FnOnce(&mut Self::Value) -> R;
91    }
92
93    impl AtomicExt for atomic::AtomicUsize {
94        type Value = usize;
95
96        fn with_mut<R, F>(&mut self, f: F) -> R
97        where
98            F: FnOnce(&mut Self::Value) -> R,
99        {
100            f(self.get_mut())
101        }
102    }
103
104    impl<T> AtomicExt for atomic::AtomicPtr<T> {
105        type Value = *mut T;
106
107        fn with_mut<R, F>(&mut self, f: F) -> R
108        where
109            F: FnOnce(&mut Self::Value) -> R,
110        {
111            f(self.get_mut())
112        }
113    }
114}