From 2d3c8596affd05cb5c9d2f0e5bd92c072e923e98 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Thu, 18 Apr 2024 21:46:04 +1000 Subject: [PATCH] Replace vendored `OnceLock` with dep `once_cell` Signed-off-by: Jiahao XU --- Cargo.toml | 3 +- src/parallel/job_token.rs | 12 ++-- src/parallel/mod.rs | 1 - src/parallel/once_lock.rs | 127 -------------------------------------- 4 files changed, 9 insertions(+), 134 deletions(-) delete mode 100644 src/parallel/once_lock.rs diff --git a/Cargo.toml b/Cargo.toml index 299b675b..3b3fb02a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,9 +26,10 @@ jobserver = { version = "0.1.30", default-features = false, optional = true } # Don't turn on the feature "std" for this, see https://github.com/rust-lang/cargo/issues/4866 # which is still an issue with `resolver = "1"`. libc = { version = "0.2.62", default-features = false, optional = true } +once_cell = { version = "1.19", optional = true } [features] -parallel = ["libc", "jobserver"] +parallel = ["libc", "jobserver", "once_cell"] [dev-dependencies] tempfile = "3" diff --git a/src/parallel/job_token.rs b/src/parallel/job_token.rs index f164ebd0..5728da6a 100644 --- a/src/parallel/job_token.rs +++ b/src/parallel/job_token.rs @@ -1,6 +1,8 @@ use std::marker::PhantomData; -use crate::{parallel::once_lock::OnceLock, Error}; +use crate::Error; + +use once_cell::sync::OnceCell; pub(crate) struct JobToken(PhantomData<()>); @@ -34,7 +36,7 @@ impl JobTokenServer { /// that has to be static so that it will be shared by all cc /// compilation. fn new() -> &'static Self { - static JOBSERVER: OnceLock = OnceLock::new(); + static JOBSERVER: OnceCell = OnceCell::new(); JOBSERVER.get_or_init(|| { unsafe { inherited_jobserver::JobServer::from_env() } @@ -70,7 +72,7 @@ impl ActiveJobTokenServer { } mod inherited_jobserver { - use super::{JobToken, OnceLock}; + use super::{JobToken, OnceCell}; use crate::{parallel::async_executor::YieldOnce, Error, ErrorKind}; @@ -136,7 +138,7 @@ mod inherited_jobserver { pub(super) fn enter_active(&self) -> Result, Error> { Ok(ActiveJobServer { jobserver: self, - helper_thread: OnceLock::new(), + helper_thread: OnceCell::new(), }) } } @@ -162,7 +164,7 @@ mod inherited_jobserver { pub(crate) struct ActiveJobServer<'a> { jobserver: &'a JobServer, - helper_thread: OnceLock, + helper_thread: OnceCell, } impl<'a> ActiveJobServer<'a> { diff --git a/src/parallel/mod.rs b/src/parallel/mod.rs index 70a56e74..019eae10 100644 --- a/src/parallel/mod.rs +++ b/src/parallel/mod.rs @@ -1,4 +1,3 @@ pub(crate) mod async_executor; pub(crate) mod job_token; -pub(crate) mod once_lock; pub(crate) mod stderr; diff --git a/src/parallel/once_lock.rs b/src/parallel/once_lock.rs deleted file mode 100644 index 4e911ffd..00000000 --- a/src/parallel/once_lock.rs +++ /dev/null @@ -1,127 +0,0 @@ -//! Copied from `std::sync::OnceLock` -//! TODO: Remove this once `OnceLock::get_or_try_init` -//! is initialised and MSRV is high enoguh to use it. - -use std::{ - cell::UnsafeCell, - convert::Infallible, - marker::PhantomData, - mem::MaybeUninit, - panic::{RefUnwindSafe, UnwindSafe}, - sync::Once, -}; - -pub struct OnceLock { - once: Once, - // Whether or not the value is initialized is tracked by `once.is_completed()`. - value: UnsafeCell>, - /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl. - /// - /// ```compile_fail,E0597 - - /// use std::sync::OnceLock; - /// - /// struct A<'a>(&'a str); - /// - /// impl<'a> Drop for A<'a> { - /// fn drop(&mut self) {} - /// } - /// - /// let cell = OnceLock::new(); - /// { - /// let s = String::new(); - /// let _ = cell.set(A(&s)); - /// } - /// ``` - _marker: PhantomData, -} - -unsafe impl Sync for OnceLock {} -unsafe impl Send for OnceLock {} - -impl RefUnwindSafe for OnceLock {} -impl UnwindSafe for OnceLock {} - -impl OnceLock { - pub const fn new() -> OnceLock { - OnceLock { - once: Once::new(), - value: UnsafeCell::new(MaybeUninit::uninit()), - _marker: PhantomData, - } - } - - pub fn get(&self) -> Option<&T> { - if self.is_initialized() { - // Safe b/c checked is_initialized - Some(unsafe { self.get_unchecked() }) - } else { - None - } - } - - pub fn get_or_init(&self, f: F) -> &T - where - F: FnOnce() -> T, - { - match self.get_or_try_init(|| Ok::(f())) { - Ok(val) => val, - Err(err) => match err {}, - } - } - - pub fn get_or_try_init(&self, f: F) -> Result<&T, E> - where - F: FnOnce() -> Result, - { - // Fast path check - // NOTE: We need to perform an acquire on the state in this method - // in order to correctly synchronize `LazyLock::force`. This is - // currently done by calling `self.get()`, which in turn calls - // `self.is_initialized()`, which in turn performs the acquire. - if let Some(value) = self.get() { - return Ok(value); - } - self.initialize(f)?; - - debug_assert!(self.is_initialized()); - - // SAFETY: The inner value has been initialized - Ok(unsafe { self.get_unchecked() }) - } - - #[inline] - fn is_initialized(&self) -> bool { - self.once.is_completed() - } - - #[cold] - fn initialize(&self, f: F) -> Result<(), E> - where - F: FnOnce() -> Result, - { - let mut res: Result<(), E> = Ok(()); - let slot = &self.value; - - // Ignore poisoning from other threads - // If another thread panics, then we'll be able to run our closure - self.once.call_once_force(|_| match f() { - Ok(value) => { - unsafe { (&mut *slot.get()).write(value) }; - } - Err(e) => { - res = Err(e); - } - }); - res - } - - /// # Safety - /// - /// The value must be initialized - #[inline] - unsafe fn get_unchecked(&self) -> &T { - debug_assert!(self.is_initialized()); - (&*self.value.get()).assume_init_ref() - } -}