1#![forbid(unsafe_code)]
6#![warn(rust_2018_idioms)]
7#![no_std]
8
9#[cfg(not(feature = "atomic"))]
10use core::cell::Cell;
11#[cfg(feature = "atomic")]
12use core::sync::atomic::{
13 AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
14 AtomicU64, AtomicU8, AtomicUsize,
15};
16
17use core::sync::atomic::Ordering;
18use doc_comment::doc_comment;
19
20macro_rules! maybe_atomic_type {
21 ($tyname: ident: $atomic: ty | $unsync: ty) => {
22 doc_comment! {
23 concat!(
24 "An atomic structure that wraps either an ",
25 stringify!($atomic),
26 " or a ",
27 stringify!($unsync),
28 ", depending on if atomics are available."
29 ),
30 #[repr(transparent)]
31 pub struct $tyname {
32 #[cfg(feature = "atomic")]
33 atomic: $atomic,
34 #[cfg(not(feature = "atomic"))]
35 unsync: Cell<$unsync>,
36 }
37 }
38
39 impl $tyname {
40 doc_comment! {
41 concat!(
42 "Creates a new instance of ",
43 stringify!($tyname),
44 "."
45 ),
46 #[inline]
47 pub fn new(inner: $unsync) -> Self {
48 Self::new_impl(inner)
49 }
50 }
51
52 #[cfg(feature = "atomic")]
53 #[inline]
54 fn new_impl(inner: $unsync) -> Self {
55 Self {
56 atomic: <$atomic>::new(inner),
57 }
58 }
59
60 #[cfg(not(feature = "atomic"))]
61 #[inline]
62 fn new_impl(inner: $unsync) -> Self {
63 Self {
64 unsync: Cell::new(inner),
65 }
66 }
67
68 #[inline]
70 pub fn get_mut(&mut self) -> &mut $unsync {
71 self.get_mut_impl()
72 }
73
74 #[cfg(feature = "atomic")]
75 #[inline]
76 fn get_mut_impl(&mut self) -> &mut $unsync {
77 self.atomic.get_mut()
78 }
79
80 #[cfg(not(feature = "atomic"))]
81 #[inline]
82 fn get_mut_impl(&mut self) -> &mut $unsync {
83 self.unsync.get_mut()
84 }
85
86 #[inline]
88 pub fn load(&self, order: Ordering) -> $unsync {
89 self.load_impl(order)
90 }
91
92 #[cfg(feature = "atomic")]
93 #[inline]
94 fn load_impl(&self, order: Ordering) -> $unsync {
95 self.atomic.load(order)
96 }
97
98 #[cfg(not(feature = "atomic"))]
99 #[inline]
100 fn load_impl(&self, _order: Ordering) -> $unsync {
101 self.unsync.get()
102 }
103
104 #[inline]
106 pub fn store(&self, val: $unsync, order: Ordering) {
107 self.store_impl(val, order);
108 }
109
110 #[cfg(feature = "atomic")]
111 #[inline]
112 fn store_impl(&self, val: $unsync, order: Ordering) {
113 self.atomic.store(val, order);
114 }
115
116 #[cfg(not(feature = "atomic"))]
117 #[inline]
118 fn store_impl(&self, val: $unsync, _order: Ordering) {
119 self.unsync.set(val);
120 }
121
122 #[inline]
124 pub fn swap(&self, val: $unsync, order: Ordering) -> $unsync {
125 self.swap_impl(val, order)
126 }
127
128 #[cfg(feature = "atomic")]
129 #[inline]
130 fn swap_impl(&self, val: $unsync, order: Ordering) -> $unsync {
131 self.atomic.swap(val, order)
132 }
133
134 #[cfg(not(feature = "atomic"))]
135 #[inline]
136 fn swap_impl(&self, val: $unsync, _order: Ordering) -> $unsync {
137 self.unsync.replace(val)
138 }
139 }
140 };
141}
142
143maybe_atomic_type! {MaybeAtomicBool: AtomicBool | bool}
144maybe_atomic_type! {MaybeAtomicU8: AtomicU8 | u8}
145maybe_atomic_type! {MaybeAtomicU16: AtomicU16 | u16}
146maybe_atomic_type! {MaybeAtomicU32: AtomicU32 | u32}
147maybe_atomic_type! {MaybeAtomicU64: AtomicU64 | u64}
148maybe_atomic_type! {MaybeAtomicUsize: AtomicUsize | usize}
149maybe_atomic_type! {MaybeAtomicI8: AtomicI8 | i8}
150maybe_atomic_type! {MaybeAtomicI16: AtomicI16 | i16}
151maybe_atomic_type! {MaybeAtomicI32: AtomicI32 | i32}
152maybe_atomic_type! {MaybeAtomicI64: AtomicI64 | i64}
153maybe_atomic_type! {MaybeAtomicIsize: AtomicIsize | isize}