1 | //! Synchronization utilities. |
2 | |
3 | #![cfg_attr (not(target_os = "macos" ), allow(unused))] |
4 | |
5 | use std::{ |
6 | ops::{Deref, DerefMut}, |
7 | sync::atomic::*, |
8 | }; |
9 | |
10 | /// Makes the wrapped value [`Send`] + [`Sync`] even though it isn't. |
11 | pub struct SyncWrap<T> { |
12 | pub value: T, |
13 | } |
14 | |
15 | unsafe impl<T> Sync for SyncWrap<T> {} |
16 | |
17 | impl<T> Deref for SyncWrap<T> { |
18 | type Target = T; |
19 | |
20 | #[inline ] |
21 | fn deref(&self) -> &Self::Target { |
22 | &self.value |
23 | } |
24 | } |
25 | |
26 | impl<T> DerefMut for SyncWrap<T> { |
27 | #[inline ] |
28 | fn deref_mut(&mut self) -> &mut Self::Target { |
29 | &mut self.value |
30 | } |
31 | } |
32 | |
33 | impl<T> SyncWrap<T> { |
34 | #[inline ] |
35 | pub const unsafe fn new(value: T) -> Self { |
36 | Self { value } |
37 | } |
38 | } |
39 | |
40 | /// A convenience wrapper around `AtomicBool`. |
41 | pub(crate) struct AtomicFlag(AtomicBool); |
42 | |
43 | impl AtomicFlag { |
44 | #[inline ] |
45 | pub const fn new(value: bool) -> Self { |
46 | Self(AtomicBool::new(value)) |
47 | } |
48 | |
49 | #[inline ] |
50 | pub fn get(&self) -> bool { |
51 | self.0.load(order:Ordering::Relaxed) |
52 | } |
53 | |
54 | #[inline ] |
55 | pub fn set(&self, value: bool) { |
56 | self.0.store(val:value, order:Ordering::Relaxed); |
57 | } |
58 | } |
59 | |
60 | /// Prevents false sharing by aligning to the cache line. |
61 | #[derive (Clone, Copy)] |
62 | #[repr (align(64))] |
63 | pub(crate) struct CachePadded<T>(pub T); |
64 | |
65 | /// Alias to the atomic equivalent of `T`. |
66 | pub(crate) type Atomic<T> = <T as WithAtomic>::Atomic; |
67 | |
68 | /// A type with an associated atomic type. |
69 | pub(crate) trait WithAtomic { |
70 | type Atomic; |
71 | } |
72 | |
73 | #[cfg (target_has_atomic = "ptr" )] |
74 | impl WithAtomic for usize { |
75 | type Atomic = AtomicUsize; |
76 | } |
77 | |
78 | #[cfg (target_has_atomic = "ptr" )] |
79 | impl WithAtomic for isize { |
80 | type Atomic = AtomicIsize; |
81 | } |
82 | |
83 | #[cfg (target_has_atomic = "8" )] |
84 | impl WithAtomic for u8 { |
85 | type Atomic = AtomicU8; |
86 | } |
87 | |
88 | #[cfg (target_has_atomic = "8" )] |
89 | impl WithAtomic for i8 { |
90 | type Atomic = AtomicI8; |
91 | } |
92 | |
93 | #[cfg (target_has_atomic = "16" )] |
94 | impl WithAtomic for u16 { |
95 | type Atomic = AtomicU16; |
96 | } |
97 | |
98 | #[cfg (target_has_atomic = "16" )] |
99 | impl WithAtomic for i16 { |
100 | type Atomic = AtomicI16; |
101 | } |
102 | |
103 | #[cfg (target_has_atomic = "32" )] |
104 | impl WithAtomic for u32 { |
105 | type Atomic = AtomicU32; |
106 | } |
107 | |
108 | #[cfg (target_has_atomic = "32" )] |
109 | impl WithAtomic for i32 { |
110 | type Atomic = AtomicI32; |
111 | } |
112 | |
113 | #[cfg (target_has_atomic = "64" )] |
114 | impl WithAtomic for u64 { |
115 | type Atomic = AtomicU64; |
116 | } |
117 | |
118 | #[cfg (target_has_atomic = "64" )] |
119 | impl WithAtomic for i64 { |
120 | type Atomic = AtomicI64; |
121 | } |
122 | |