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 pub(crate) use loom::thread::yield_now;
40}
41
42pub(crate) use sync_impl::*;
43
44/// Notify the CPU that we are currently busy-waiting.
45#[inline]
46pub(crate) fn busy_wait() {
47 #[cfg(feature = "std")]
48 yield_now();
49
50 #[cfg(not(feature = "std"))]
51 spin_loop();
52}
53
54#[cfg(loom)]
55pub(crate) mod prelude {}
56
57#[cfg(not(loom))]
58pub(crate) mod prelude {
59 use super::{atomic, cell};
60
61 /// Emulate `loom::UnsafeCell`'s API.
62 pub(crate) trait UnsafeCellExt {
63 type Value;
64
65 fn with<R, F>(&self, f: F) -> R
66 where
67 F: FnOnce(*const Self::Value) -> R;
68
69 fn with_mut<R, F>(&self, f: F) -> R
70 where
71 F: FnOnce(*mut Self::Value) -> R;
72 }
73
74 impl<T> UnsafeCellExt for cell::UnsafeCell<T> {
75 type Value = T;
76
77 fn with<R, F>(&self, f: F) -> R
78 where
79 F: FnOnce(*const Self::Value) -> R,
80 {
81 f(self.get())
82 }
83
84 fn with_mut<R, F>(&self, f: F) -> R
85 where
86 F: FnOnce(*mut Self::Value) -> R,
87 {
88 f(self.get())
89 }
90 }
91
92 /// Emulate `loom::Atomic*`'s API.
93 pub(crate) trait AtomicExt {
94 type Value;
95
96 fn with_mut<R, F>(&mut self, f: F) -> R
97 where
98 F: FnOnce(&mut Self::Value) -> R;
99 }
100
101 impl AtomicExt for atomic::AtomicUsize {
102 type Value = usize;
103
104 fn with_mut<R, F>(&mut self, f: F) -> R
105 where
106 F: FnOnce(&mut Self::Value) -> R,
107 {
108 f(self.get_mut())
109 }
110 }
111
112 impl<T> AtomicExt for atomic::AtomicPtr<T> {
113 type Value = *mut T;
114
115 fn with_mut<R, F>(&mut self, f: F) -> R
116 where
117 F: FnOnce(&mut Self::Value) -> R,
118 {
119 f(self.get_mut())
120 }
121 }
122}
123