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