From 9f82785c81c68d117617b6b45bce437649f94833 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 15 May 2020 21:43:06 -0700 Subject: [PATCH] Replace `rustc_data_structures::sync::Once` with `OnceCell` --- Cargo.lock | 1 + src/librustc_data_structures/Cargo.toml | 1 + src/librustc_data_structures/sync.rs | 133 +----------------------- src/tools/tidy/src/deps.rs | 1 + 4 files changed, 7 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d81fd6e8d3a..ebcc11d2b26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3791,6 +3791,7 @@ dependencies = [ "libc", "log", "measureme", + "once_cell", "parking_lot 0.10.2", "rustc-hash", "rustc-rayon", diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 81ad032967b..67721220526 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -15,6 +15,7 @@ indexmap = "1" log = "0.4" jobserver_crate = { version = "0.1.13", package = "jobserver" } lazy_static = "1" +once_cell = { version = "1", features = ["parking_lot"] } rustc_serialize = { path = "../libserialize", package = "serialize" } graphviz = { path = "../libgraphviz" } cfg-if = "0.1.2" diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 9051b1751b1..39afb3d82ff 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -20,7 +20,6 @@ use crate::owning_ref::{Erased, OwningRef}; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; -use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; pub use std::sync::atomic::Ordering; @@ -230,6 +229,8 @@ cfg_if! { pub use std::cell::RefMut as LockGuard; pub use std::cell::RefMut as MappedLockGuard; + pub use once_cell::unsync::OnceCell; + use std::cell::RefCell as InnerRwLock; use std::cell::RefCell as InnerLock; @@ -313,6 +314,8 @@ cfg_if! { pub use parking_lot::MutexGuard as LockGuard; pub use parking_lot::MappedMutexGuard as MappedLockGuard; + pub use once_cell::sync::OnceCell; + pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; pub use crossbeam_utils::atomic::AtomicCell; @@ -432,134 +435,6 @@ impl HashMapExt for HashMap } } -/// A type whose inner value can be written once and then will stay read-only -// This contains a PhantomData since this type conceptually owns a T outside the Mutex once -// initialized. This ensures that Once is Sync only if T is. If we did not have PhantomData -// we could send a &Once> to multiple threads and call `get` on it to get access -// to &Cell on those threads. -pub struct Once(Lock>, PhantomData); - -impl Once { - /// Creates an Once value which is uninitialized - #[inline(always)] - pub fn new() -> Self { - Once(Lock::new(None), PhantomData) - } - - /// Consumes the value and returns Some(T) if it was initialized - #[inline(always)] - pub fn into_inner(self) -> Option { - self.0.into_inner() - } - - /// Tries to initialize the inner value to `value`. - /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it - /// otherwise if the inner value was already set it returns `value` back to the caller - #[inline] - pub fn try_set(&self, value: T) -> Option { - let mut lock = self.0.lock(); - if lock.is_some() { - return Some(value); - } - *lock = Some(value); - None - } - - /// Tries to initialize the inner value to `value`. - /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it - /// otherwise if the inner value was already set it asserts that `value` is equal to the inner - /// value and then returns `value` back to the caller - #[inline] - pub fn try_set_same(&self, value: T) -> Option - where - T: Eq, - { - let mut lock = self.0.lock(); - if let Some(ref inner) = *lock { - assert!(*inner == value); - return Some(value); - } - *lock = Some(value); - None - } - - /// Tries to initialize the inner value to `value` and panics if it was already initialized - #[inline] - pub fn set(&self, value: T) { - assert!(self.try_set(value).is_none()); - } - - /// Initializes the inner value if it wasn't already done by calling the provided closure. It - /// ensures that no-one else can access the value in the mean time by holding a lock for the - /// duration of the closure. - /// A reference to the inner value is returned. - #[inline] - pub fn init_locking T>(&self, f: F) -> &T { - { - let mut lock = self.0.lock(); - if lock.is_none() { - *lock = Some(f()); - } - } - - self.borrow() - } - - /// Tries to initialize the inner value by calling the closure without ensuring that no-one - /// else can access it. This mean when this is called from multiple threads, multiple - /// closures may concurrently be computing a value which the inner value should take. - /// Only one of these closures are used to actually initialize the value. - /// If some other closure already set the value, - /// we return the value our closure computed wrapped in a `Option`. - /// If our closure set the value, `None` is returned. - /// If the value is already initialized, the closure is not called and `None` is returned. - #[inline] - pub fn init_nonlocking T>(&self, f: F) -> Option { - if self.0.lock().is_some() { None } else { self.try_set(f()) } - } - - /// Tries to initialize the inner value by calling the closure without ensuring that no-one - /// else can access it. This mean when this is called from multiple threads, multiple - /// closures may concurrently be computing a value which the inner value should take. - /// Only one of these closures are used to actually initialize the value. - /// If some other closure already set the value, we assert that it our closure computed - /// a value equal to the value already set and then - /// we return the value our closure computed wrapped in a `Option`. - /// If our closure set the value, `None` is returned. - /// If the value is already initialized, the closure is not called and `None` is returned. - #[inline] - pub fn init_nonlocking_same T>(&self, f: F) -> Option - where - T: Eq, - { - if self.0.lock().is_some() { None } else { self.try_set_same(f()) } - } - - /// Tries to get a reference to the inner value, returns `None` if it is not yet initialized - #[inline(always)] - pub fn try_get(&self) -> Option<&T> { - let lock = &*self.0.lock(); - if let Some(ref inner) = *lock { - // This is safe since we won't mutate the inner value - unsafe { Some(&*(inner as *const T)) } - } else { - None - } - } - - /// Gets reference to the inner value, panics if it is not yet initialized - #[inline(always)] - pub fn get(&self) -> &T { - self.try_get().expect("value was not set") - } - - /// Gets reference to the inner value, panics if it is not yet initialized - #[inline(always)] - pub fn borrow(&self) -> &T { - self.get() - } -} - #[derive(Debug)] pub struct Lock(InnerLock); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index d3c7b7a068b..61389028cc7 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -128,6 +128,7 @@ const WHITELIST: &[&str] = &[ "miniz_oxide", "nodrop", "num_cpus", + "once_cell", "opaque-debug", "parking_lot", "parking_lot_core",