rustc_data_structures/
sync.rs1use std::collections::HashMap;
26use std::hash::{BuildHasher, Hash};
27
28pub use parking_lot::{
29 MappedRwLockReadGuard as MappedReadGuard, MappedRwLockWriteGuard as MappedWriteGuard,
30 RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
31};
32
33pub use self::atomic::AtomicU64;
34pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
35#[doc(no_inline)]
36pub use self::lock::{Lock, LockGuard, Mode};
37pub use self::mode::{
38 FromDyn, check_dyn_thread_safe, is_dyn_thread_safe, set_dyn_thread_safe_mode,
39};
40pub use self::parallel::{
41 broadcast, par_fns, par_for_each_in, par_join, par_map, parallel_guard, spawn,
42 try_par_for_each_in,
43};
44pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec};
45pub use self::worker_local::{Registry, WorkerLocal};
46pub use crate::marker::*;
47
48mod freeze;
49mod lock;
50mod parallel;
51mod vec;
52mod worker_local;
53
54mod atomic {
57 #[cfg(target_has_atomic = "64")]
59 pub use std::sync::atomic::AtomicU64;
60
61 #[cfg(not(target_has_atomic = "64"))]
63 pub use portable_atomic::AtomicU64;
64}
65
66mod mode {
67 use std::sync::atomic::{AtomicU8, Ordering};
68
69 use crate::sync::{DynSend, DynSync};
70
71 const UNINITIALIZED: u8 = 0;
72 const DYN_NOT_THREAD_SAFE: u8 = 1;
73 const DYN_THREAD_SAFE: u8 = 2;
74
75 static DYN_THREAD_SAFE_MODE: AtomicU8 = AtomicU8::new(UNINITIALIZED);
76
77 #[inline]
79 pub fn check_dyn_thread_safe() -> Option<FromDyn<()>> {
80 is_dyn_thread_safe().then_some(FromDyn(()))
81 }
82
83 #[inline]
85 pub fn is_dyn_thread_safe() -> bool {
86 match DYN_THREAD_SAFE_MODE.load(Ordering::Relaxed) {
87 DYN_NOT_THREAD_SAFE => false,
88 DYN_THREAD_SAFE => true,
89 _ => {
::core::panicking::panic_fmt(format_args!("uninitialized dyn_thread_safe mode!"));
}panic!("uninitialized dyn_thread_safe mode!"),
90 }
91 }
92
93 #[inline]
95 pub(super) fn might_be_dyn_thread_safe() -> bool {
96 DYN_THREAD_SAFE_MODE.load(Ordering::Relaxed) != DYN_NOT_THREAD_SAFE
97 }
98
99 pub fn set_dyn_thread_safe_mode(mode: bool) {
101 let set: u8 = if mode { DYN_THREAD_SAFE } else { DYN_NOT_THREAD_SAFE };
102 let previous = DYN_THREAD_SAFE_MODE.compare_exchange(
103 UNINITIALIZED,
104 set,
105 Ordering::Relaxed,
106 Ordering::Relaxed,
107 );
108
109 if !(previous.is_ok() || previous == Err(set)) {
::core::panicking::panic("assertion failed: previous.is_ok() || previous == Err(set)")
};assert!(previous.is_ok() || previous == Err(set));
111 }
112
113 #[derive(#[automatically_derived]
impl<T: ::core::marker::Copy> ::core::marker::Copy for FromDyn<T> { }Copy, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for FromDyn<T> {
#[inline]
fn clone(&self) -> FromDyn<T> {
FromDyn(::core::clone::Clone::clone(&self.0))
}
}Clone)]
114 pub struct FromDyn<T>(T);
115
116 impl<T> FromDyn<T> {
117 #[inline(always)]
118 pub fn derive<O>(&self, val: O) -> FromDyn<O> {
119 FromDyn(val)
121 }
122
123 #[inline(always)]
124 pub fn into_inner(self) -> T {
125 self.0
126 }
127 }
128
129 unsafe impl<T: DynSend> Send for FromDyn<T> {}
131
132 unsafe impl<T: DynSync> Sync for FromDyn<T> {}
134
135 impl<T> std::ops::Deref for FromDyn<T> {
136 type Target = T;
137
138 #[inline(always)]
139 fn deref(&self) -> &Self::Target {
140 &self.0
141 }
142 }
143
144 impl<T> std::ops::DerefMut for FromDyn<T> {
145 #[inline(always)]
146 fn deref_mut(&mut self) -> &mut Self::Target {
147 &mut self.0
148 }
149 }
150}
151
152const ERROR_CHECKING: bool = false;
155
156#[derive(#[automatically_derived]
impl<T: ::core::default::Default> ::core::default::Default for CacheAligned<T>
{
#[inline]
fn default() -> CacheAligned<T> {
CacheAligned(::core::default::Default::default())
}
}Default)]
157#[repr(align(64))]
158pub struct CacheAligned<T>(pub T);
159
160pub trait HashMapExt<K, V> {
161 fn insert_same(&mut self, key: K, value: V);
164}
165
166impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S> {
167 fn insert_same(&mut self, key: K, value: V) {
168 self.entry(key).and_modify(|old| if !(*old == value) {
::core::panicking::panic("assertion failed: *old == value")
}assert!(*old == value)).or_insert(value);
169 }
170}
171
172#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for RwLock<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "RwLock",
&&self.0)
}
}Debug, #[automatically_derived]
impl<T: ::core::default::Default> ::core::default::Default for RwLock<T> {
#[inline]
fn default() -> RwLock<T> { RwLock(::core::default::Default::default()) }
}Default)]
173pub struct RwLock<T>(parking_lot::RwLock<T>);
174
175impl<T> RwLock<T> {
176 #[inline(always)]
177 pub fn new(inner: T) -> Self {
178 RwLock(parking_lot::RwLock::new(inner))
179 }
180
181 #[inline(always)]
182 pub fn into_inner(self) -> T {
183 self.0.into_inner()
184 }
185
186 #[inline(always)]
187 pub fn get_mut(&mut self) -> &mut T {
188 self.0.get_mut()
189 }
190
191 #[inline(always)]
192 pub fn read(&self) -> ReadGuard<'_, T> {
193 if ERROR_CHECKING {
194 self.0.try_read().expect("lock was already held")
195 } else {
196 self.0.read()
197 }
198 }
199
200 #[inline(always)]
201 pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
202 self.0.try_write().ok_or(())
203 }
204
205 #[inline(always)]
206 pub fn write(&self) -> WriteGuard<'_, T> {
207 if ERROR_CHECKING {
208 self.0.try_write().expect("lock was already held")
209 } else {
210 self.0.write()
211 }
212 }
213
214 #[inline(always)]
215 #[track_caller]
216 pub fn borrow(&self) -> ReadGuard<'_, T> {
217 self.read()
218 }
219
220 #[inline(always)]
221 #[track_caller]
222 pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
223 self.write()
224 }
225}