]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_data_structures/src/sync.rs
Auto merge of #2715 - RalfJung:rustup, r=RalfJung
[rust.git] / compiler / rustc_data_structures / src / sync.rs
1 //! This module defines types which are thread safe if cfg!(parallel_compiler) is true.
2 //!
3 //! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise.
4 //!
5 //! `Lock` is a mutex.
6 //! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true,
7 //! `RefCell` otherwise.
8 //!
9 //! `RwLock` is a read-write lock.
10 //! It internally uses `parking_lot::RwLock` if cfg!(parallel_compiler) is true,
11 //! `RefCell` otherwise.
12 //!
13 //! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false.
14 //!
15 //! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise.
16 //!
17 //! `rustc_erase_owner!` erases an OwningRef owner into Erased or Erased + Send + Sync
18 //! depending on the value of cfg!(parallel_compiler).
19
20 use crate::owning_ref::{Erased, OwningRef};
21 use std::collections::HashMap;
22 use std::hash::{BuildHasher, Hash};
23 use std::ops::{Deref, DerefMut};
24 use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
25
26 pub use std::sync::atomic::Ordering;
27 pub use std::sync::atomic::Ordering::SeqCst;
28
29 cfg_if! {
30     if #[cfg(not(parallel_compiler))] {
31         pub auto trait Send {}
32         pub auto trait Sync {}
33
34         impl<T: ?Sized> Send for T {}
35         impl<T: ?Sized> Sync for T {}
36
37         #[macro_export]
38         macro_rules! rustc_erase_owner {
39             ($v:expr) => {
40                 $v.erase_owner()
41             }
42         }
43
44         use std::ops::Add;
45
46         /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
47         /// It has explicit ordering arguments and is only intended for use with
48         /// the native atomic types.
49         /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
50         /// as it's not intended to be used separately.
51         #[derive(Debug, Default)]
52         pub struct Atomic<T: Copy>(Cell<T>);
53
54         impl<T: Copy> Atomic<T> {
55             #[inline]
56             pub fn new(v: T) -> Self {
57                 Atomic(Cell::new(v))
58             }
59
60             #[inline]
61             pub fn into_inner(self) -> T {
62                 self.0.into_inner()
63             }
64
65             #[inline]
66             pub fn load(&self, _: Ordering) -> T {
67                 self.0.get()
68             }
69
70             #[inline]
71             pub fn store(&self, val: T, _: Ordering) {
72                 self.0.set(val)
73             }
74
75             #[inline]
76             pub fn swap(&self, val: T, _: Ordering) -> T {
77                 self.0.replace(val)
78             }
79         }
80
81         impl<T: Copy + PartialEq> Atomic<T> {
82             #[inline]
83             pub fn compare_exchange(&self,
84                                     current: T,
85                                     new: T,
86                                     _: Ordering,
87                                     _: Ordering)
88                                     -> Result<T, T> {
89                 let read = self.0.get();
90                 if read == current {
91                     self.0.set(new);
92                     Ok(read)
93                 } else {
94                     Err(read)
95                 }
96             }
97         }
98
99         impl<T: Add<Output=T> + Copy> Atomic<T> {
100             #[inline]
101             pub fn fetch_add(&self, val: T, _: Ordering) -> T {
102                 let old = self.0.get();
103                 self.0.set(old + val);
104                 old
105             }
106         }
107
108         pub type AtomicUsize = Atomic<usize>;
109         pub type AtomicBool = Atomic<bool>;
110         pub type AtomicU32 = Atomic<u32>;
111         pub type AtomicU64 = Atomic<u64>;
112
113         pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
114             where A: FnOnce() -> RA,
115                   B: FnOnce() -> RB
116         {
117             (oper_a(), oper_b())
118         }
119
120         #[macro_export]
121         macro_rules! parallel {
122             ($($blocks:tt),*) => {
123                 // We catch panics here ensuring that all the blocks execute.
124                 // This makes behavior consistent with the parallel compiler.
125                 let mut panic = None;
126                 $(
127                     if let Err(p) = ::std::panic::catch_unwind(
128                         ::std::panic::AssertUnwindSafe(|| $blocks)
129                     ) {
130                         if panic.is_none() {
131                             panic = Some(p);
132                         }
133                     }
134                 )*
135                 if let Some(panic) = panic {
136                     ::std::panic::resume_unwind(panic);
137                 }
138             }
139         }
140
141         pub use std::iter::Iterator as ParallelIterator;
142
143         pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
144             t.into_iter()
145         }
146
147         pub fn par_for_each_in<T: IntoIterator>(t: T, mut for_each: impl FnMut(T::Item) + Sync + Send) {
148             // We catch panics here ensuring that all the loop iterations execute.
149             // This makes behavior consistent with the parallel compiler.
150             let mut panic = None;
151             t.into_iter().for_each(|i| {
152                 if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
153                     if panic.is_none() {
154                         panic = Some(p);
155                     }
156                 }
157             });
158             if let Some(panic) = panic {
159                 resume_unwind(panic);
160             }
161         }
162
163         pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>;
164
165         pub use std::rc::Rc as Lrc;
166         pub use std::rc::Weak as Weak;
167         pub use std::cell::Ref as ReadGuard;
168         pub use std::cell::Ref as MappedReadGuard;
169         pub use std::cell::RefMut as WriteGuard;
170         pub use std::cell::RefMut as MappedWriteGuard;
171         pub use std::cell::RefMut as LockGuard;
172         pub use std::cell::RefMut as MappedLockGuard;
173
174         pub use std::cell::OnceCell;
175
176         use std::cell::RefCell as InnerRwLock;
177         use std::cell::RefCell as InnerLock;
178
179         use std::cell::Cell;
180
181         #[derive(Debug)]
182         pub struct WorkerLocal<T>(OneThread<T>);
183
184         impl<T> WorkerLocal<T> {
185             /// Creates a new worker local where the `initial` closure computes the
186             /// value this worker local should take for each thread in the thread pool.
187             #[inline]
188             pub fn new<F: FnMut(usize) -> T>(mut f: F) -> WorkerLocal<T> {
189                 WorkerLocal(OneThread::new(f(0)))
190             }
191
192             /// Returns the worker-local value for each thread
193             #[inline]
194             pub fn into_inner(self) -> Vec<T> {
195                 vec![OneThread::into_inner(self.0)]
196             }
197         }
198
199         impl<T> Deref for WorkerLocal<T> {
200             type Target = T;
201
202             #[inline(always)]
203             fn deref(&self) -> &T {
204                 &self.0
205             }
206         }
207
208         pub type MTRef<'a, T> = &'a mut T;
209
210         #[derive(Debug, Default)]
211         pub struct MTLock<T>(T);
212
213         impl<T> MTLock<T> {
214             #[inline(always)]
215             pub fn new(inner: T) -> Self {
216                 MTLock(inner)
217             }
218
219             #[inline(always)]
220             pub fn into_inner(self) -> T {
221                 self.0
222             }
223
224             #[inline(always)]
225             pub fn get_mut(&mut self) -> &mut T {
226                 &mut self.0
227             }
228
229             #[inline(always)]
230             pub fn lock(&self) -> &T {
231                 &self.0
232             }
233
234             #[inline(always)]
235             pub fn lock_mut(&mut self) -> &mut T {
236                 &mut self.0
237             }
238         }
239
240         // FIXME: Probably a bad idea (in the threaded case)
241         impl<T: Clone> Clone for MTLock<T> {
242             #[inline]
243             fn clone(&self) -> Self {
244                 MTLock(self.0.clone())
245             }
246         }
247     } else {
248         pub use std::marker::Send as Send;
249         pub use std::marker::Sync as Sync;
250
251         pub use parking_lot::RwLockReadGuard as ReadGuard;
252         pub use parking_lot::MappedRwLockReadGuard as MappedReadGuard;
253         pub use parking_lot::RwLockWriteGuard as WriteGuard;
254         pub use parking_lot::MappedRwLockWriteGuard as MappedWriteGuard;
255
256         pub use parking_lot::MutexGuard as LockGuard;
257         pub use parking_lot::MappedMutexGuard as MappedLockGuard;
258
259         pub use std::sync::OnceLock as OnceCell;
260
261         pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
262
263         pub use std::sync::Arc as Lrc;
264         pub use std::sync::Weak as Weak;
265
266         pub type MTRef<'a, T> = &'a T;
267
268         #[derive(Debug, Default)]
269         pub struct MTLock<T>(Lock<T>);
270
271         impl<T> MTLock<T> {
272             #[inline(always)]
273             pub fn new(inner: T) -> Self {
274                 MTLock(Lock::new(inner))
275             }
276
277             #[inline(always)]
278             pub fn into_inner(self) -> T {
279                 self.0.into_inner()
280             }
281
282             #[inline(always)]
283             pub fn get_mut(&mut self) -> &mut T {
284                 self.0.get_mut()
285             }
286
287             #[inline(always)]
288             pub fn lock(&self) -> LockGuard<'_, T> {
289                 self.0.lock()
290             }
291
292             #[inline(always)]
293             pub fn lock_mut(&self) -> LockGuard<'_, T> {
294                 self.lock()
295             }
296         }
297
298         use parking_lot::Mutex as InnerLock;
299         use parking_lot::RwLock as InnerRwLock;
300
301         use std::thread;
302         pub use rayon::{join, scope};
303
304         /// Runs a list of blocks in parallel. The first block is executed immediately on
305         /// the current thread. Use that for the longest running block.
306         #[macro_export]
307         macro_rules! parallel {
308             (impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
309                 parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
310             };
311             (impl $fblock:tt [$($blocks:tt,)*] []) => {
312                 ::rustc_data_structures::sync::scope(|s| {
313                     $(
314                         s.spawn(|_| $blocks);
315                     )*
316                     $fblock;
317                 })
318             };
319             ($fblock:tt, $($blocks:tt),*) => {
320                 // Reverse the order of the later blocks since Rayon executes them in reverse order
321                 // when using a single thread. This ensures the execution order matches that
322                 // of a single threaded rustc
323                 parallel!(impl $fblock [] [$($blocks),*]);
324             };
325         }
326
327         pub use rayon_core::WorkerLocal;
328
329         pub use rayon::iter::ParallelIterator;
330         use rayon::iter::IntoParallelIterator;
331
332         pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
333             t.into_par_iter()
334         }
335
336         pub fn par_for_each_in<T: IntoParallelIterator>(
337             t: T,
338             for_each: impl Fn(T::Item) + Sync + Send,
339         ) {
340             let ps: Vec<_> = t.into_par_iter().map(|i| catch_unwind(AssertUnwindSafe(|| for_each(i)))).collect();
341             ps.into_iter().for_each(|p| if let Err(panic) = p {
342                 resume_unwind(panic)
343             });
344         }
345
346         pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>;
347
348         /// This makes locks panic if they are already held.
349         /// It is only useful when you are running in a single thread
350         const ERROR_CHECKING: bool = false;
351
352         #[macro_export]
353         macro_rules! rustc_erase_owner {
354             ($v:expr) => {{
355                 let v = $v;
356                 ::rustc_data_structures::sync::assert_send_val(&v);
357                 v.erase_send_sync_owner()
358             }}
359         }
360     }
361 }
362
363 pub fn assert_sync<T: ?Sized + Sync>() {}
364 pub fn assert_send<T: ?Sized + Send>() {}
365 pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
366 pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
367
368 pub trait HashMapExt<K, V> {
369     /// Same as HashMap::insert, but it may panic if there's already an
370     /// entry for `key` with a value not equal to `value`
371     fn insert_same(&mut self, key: K, value: V);
372 }
373
374 impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S> {
375     fn insert_same(&mut self, key: K, value: V) {
376         self.entry(key).and_modify(|old| assert!(*old == value)).or_insert(value);
377     }
378 }
379
380 #[derive(Debug)]
381 pub struct Lock<T>(InnerLock<T>);
382
383 impl<T> Lock<T> {
384     #[inline(always)]
385     pub fn new(inner: T) -> Self {
386         Lock(InnerLock::new(inner))
387     }
388
389     #[inline(always)]
390     pub fn into_inner(self) -> T {
391         self.0.into_inner()
392     }
393
394     #[inline(always)]
395     pub fn get_mut(&mut self) -> &mut T {
396         self.0.get_mut()
397     }
398
399     #[cfg(parallel_compiler)]
400     #[inline(always)]
401     pub fn try_lock(&self) -> Option<LockGuard<'_, T>> {
402         self.0.try_lock()
403     }
404
405     #[cfg(not(parallel_compiler))]
406     #[inline(always)]
407     pub fn try_lock(&self) -> Option<LockGuard<'_, T>> {
408         self.0.try_borrow_mut().ok()
409     }
410
411     #[cfg(parallel_compiler)]
412     #[inline(always)]
413     #[track_caller]
414     pub fn lock(&self) -> LockGuard<'_, T> {
415         if ERROR_CHECKING {
416             self.0.try_lock().expect("lock was already held")
417         } else {
418             self.0.lock()
419         }
420     }
421
422     #[cfg(not(parallel_compiler))]
423     #[inline(always)]
424     #[track_caller]
425     pub fn lock(&self) -> LockGuard<'_, T> {
426         self.0.borrow_mut()
427     }
428
429     #[inline(always)]
430     #[track_caller]
431     pub fn with_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
432         f(&mut *self.lock())
433     }
434
435     #[inline(always)]
436     #[track_caller]
437     pub fn borrow(&self) -> LockGuard<'_, T> {
438         self.lock()
439     }
440
441     #[inline(always)]
442     #[track_caller]
443     pub fn borrow_mut(&self) -> LockGuard<'_, T> {
444         self.lock()
445     }
446 }
447
448 impl<T: Default> Default for Lock<T> {
449     #[inline]
450     fn default() -> Self {
451         Lock::new(T::default())
452     }
453 }
454
455 // FIXME: Probably a bad idea
456 impl<T: Clone> Clone for Lock<T> {
457     #[inline]
458     fn clone(&self) -> Self {
459         Lock::new(self.borrow().clone())
460     }
461 }
462
463 #[derive(Debug, Default)]
464 pub struct RwLock<T>(InnerRwLock<T>);
465
466 impl<T> RwLock<T> {
467     #[inline(always)]
468     pub fn new(inner: T) -> Self {
469         RwLock(InnerRwLock::new(inner))
470     }
471
472     #[inline(always)]
473     pub fn into_inner(self) -> T {
474         self.0.into_inner()
475     }
476
477     #[inline(always)]
478     pub fn get_mut(&mut self) -> &mut T {
479         self.0.get_mut()
480     }
481
482     #[cfg(not(parallel_compiler))]
483     #[inline(always)]
484     #[track_caller]
485     pub fn read(&self) -> ReadGuard<'_, T> {
486         self.0.borrow()
487     }
488
489     #[cfg(parallel_compiler)]
490     #[inline(always)]
491     pub fn read(&self) -> ReadGuard<'_, T> {
492         if ERROR_CHECKING {
493             self.0.try_read().expect("lock was already held")
494         } else {
495             self.0.read()
496         }
497     }
498
499     #[inline(always)]
500     #[track_caller]
501     pub fn with_read_lock<F: FnOnce(&T) -> R, R>(&self, f: F) -> R {
502         f(&*self.read())
503     }
504
505     #[cfg(not(parallel_compiler))]
506     #[inline(always)]
507     pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
508         self.0.try_borrow_mut().map_err(|_| ())
509     }
510
511     #[cfg(parallel_compiler)]
512     #[inline(always)]
513     pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
514         self.0.try_write().ok_or(())
515     }
516
517     #[cfg(not(parallel_compiler))]
518     #[inline(always)]
519     #[track_caller]
520     pub fn write(&self) -> WriteGuard<'_, T> {
521         self.0.borrow_mut()
522     }
523
524     #[cfg(parallel_compiler)]
525     #[inline(always)]
526     pub fn write(&self) -> WriteGuard<'_, T> {
527         if ERROR_CHECKING {
528             self.0.try_write().expect("lock was already held")
529         } else {
530             self.0.write()
531         }
532     }
533
534     #[inline(always)]
535     #[track_caller]
536     pub fn with_write_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
537         f(&mut *self.write())
538     }
539
540     #[inline(always)]
541     #[track_caller]
542     pub fn borrow(&self) -> ReadGuard<'_, T> {
543         self.read()
544     }
545
546     #[inline(always)]
547     #[track_caller]
548     pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
549         self.write()
550     }
551
552     #[cfg(not(parallel_compiler))]
553     #[inline(always)]
554     pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> {
555         ReadGuard::clone(rg)
556     }
557
558     #[cfg(parallel_compiler)]
559     #[inline(always)]
560     pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> {
561         ReadGuard::rwlock(&rg).read()
562     }
563
564     #[cfg(not(parallel_compiler))]
565     #[inline(always)]
566     pub fn leak(&self) -> &T {
567         ReadGuard::leak(self.read())
568     }
569
570     #[cfg(parallel_compiler)]
571     #[inline(always)]
572     pub fn leak(&self) -> &T {
573         let guard = self.read();
574         let ret = unsafe { &*(&*guard as *const T) };
575         std::mem::forget(guard);
576         ret
577     }
578 }
579
580 // FIXME: Probably a bad idea
581 impl<T: Clone> Clone for RwLock<T> {
582     #[inline]
583     fn clone(&self) -> Self {
584         RwLock::new(self.borrow().clone())
585     }
586 }
587
588 /// A type which only allows its inner value to be used in one thread.
589 /// It will panic if it is used on multiple threads.
590 #[derive(Debug)]
591 pub struct OneThread<T> {
592     #[cfg(parallel_compiler)]
593     thread: thread::ThreadId,
594     inner: T,
595 }
596
597 #[cfg(parallel_compiler)]
598 unsafe impl<T> std::marker::Sync for OneThread<T> {}
599 #[cfg(parallel_compiler)]
600 unsafe impl<T> std::marker::Send for OneThread<T> {}
601
602 impl<T> OneThread<T> {
603     #[inline(always)]
604     fn check(&self) {
605         #[cfg(parallel_compiler)]
606         assert_eq!(thread::current().id(), self.thread);
607     }
608
609     #[inline(always)]
610     pub fn new(inner: T) -> Self {
611         OneThread {
612             #[cfg(parallel_compiler)]
613             thread: thread::current().id(),
614             inner,
615         }
616     }
617
618     #[inline(always)]
619     pub fn into_inner(value: Self) -> T {
620         value.check();
621         value.inner
622     }
623 }
624
625 impl<T> Deref for OneThread<T> {
626     type Target = T;
627
628     fn deref(&self) -> &T {
629         self.check();
630         &self.inner
631     }
632 }
633
634 impl<T> DerefMut for OneThread<T> {
635     fn deref_mut(&mut self) -> &mut T {
636         self.check();
637         &mut self.inner
638     }
639 }