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