about summary refs log tree commit diff
path: root/src/librustc_data_structures
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-04-01 09:43:19 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-04-10 14:39:33 +0200
commite5a602e364d5083a4c475747ad08c81ef29897bf (patch)
treed134fde8d1760faea24523e217afe4e5f9ef9a57 /src/librustc_data_structures
parent67712d79451b042b6fca2167c1a57d91d86f663b (diff)
downloadrust-e5a602e364d5083a4c475747ad08c81ef29897bf.tar.gz
rust-e5a602e364d5083a4c475747ad08c81ef29897bf.zip
Add OneThread which only allows its inner value to be used in one thread
Diffstat (limited to 'src/librustc_data_structures')
-rw-r--r--src/librustc_data_structures/sync.rs55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index 0f534f0adec..ad524916f0c 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -33,6 +33,8 @@ use std::cmp::Ordering;
 use std::fmt::Debug;
 use std::fmt::Formatter;
 use std::fmt;
+use std;
+use std::ops::{Deref, DerefMut};
 use owning_ref::{Erased, OwningRef};
 
 cfg_if! {
@@ -161,6 +163,8 @@ cfg_if! {
         use parking_lot::Mutex as InnerLock;
         use parking_lot::RwLock as InnerRwLock;
 
+        use std::thread;
+
         pub type MetadataRef = OwningRef<Box<Erased + Send + Sync>, [u8]>;
 
         /// This makes locks panic if they are already held.
@@ -439,3 +443,54 @@ impl<T: Clone> Clone for RwLock<T> {
         RwLock::new(self.borrow().clone())
     }
 }
+
+/// A type which only allows its inner value to be used in one thread.
+/// It will panic if it is used on multiple threads.
+#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)]
+pub struct OneThread<T> {
+    #[cfg(parallel_queries)]
+    thread: thread::ThreadId,
+    inner: T,
+}
+
+unsafe impl<T> std::marker::Sync for OneThread<T> {}
+unsafe impl<T> std::marker::Send for OneThread<T> {}
+
+impl<T> OneThread<T> {
+    #[inline(always)]
+    fn check(&self) {
+        #[cfg(parallel_queries)]
+        assert_eq!(thread::current().id(), self.thread);
+    }
+
+    #[inline(always)]
+    pub fn new(inner: T) -> Self {
+        OneThread {
+            #[cfg(parallel_queries)]
+            thread: thread::current().id(),
+            inner,
+        }
+    }
+
+    #[inline(always)]
+    pub fn into_inner(value: Self) -> T {
+        value.check();
+        value.inner
+    }
+}
+
+impl<T> Deref for OneThread<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        self.check();
+        &self.inner
+    }
+}
+
+impl<T> DerefMut for OneThread<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        self.check();
+        &mut self.inner
+    }
+}