Skip to content

Commit

Permalink
Fix cyclic compilation: Use vendored once_cell (#1154)
Browse files Browse the repository at this point in the history
  • Loading branch information
NobodyXu authored Jul 15, 2024
1 parent 1f82ef0 commit af4c928
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 14 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ rust-version = "1.63"

[dependencies]
jobserver = { version = "0.1.30", default-features = false, optional = true }
once_cell = { version = "1.19", optional = true }

[target.'cfg(unix)'.dependencies]
# 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 }

[features]
parallel = ["dep:libc", "dep:jobserver", "dep:once_cell"]
parallel = ["dep:libc", "dep:jobserver"]
# This is a placeholder feature for people who incorrectly used `cc` with `features = ["jobserver"]`
# so that they aren't broken. This has never enabled `parallel`, so we won't do that.
jobserver = []
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1502,7 +1502,7 @@ impl Build {
}

// Limit our parallelism globally with a jobserver.
let tokens = parallel::job_token::ActiveJobTokenServer::new();
let mut tokens = parallel::job_token::ActiveJobTokenServer::new();

// When compiling objects in parallel we do a few dirty tricks to speed
// things up:
Expand Down
25 changes: 14 additions & 11 deletions src/parallel/job_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::marker::PhantomData;

use crate::Error;

use once_cell::sync::OnceCell;
use super::once_lock::OnceLock;

pub(crate) struct JobToken(PhantomData<()>);

Expand Down Expand Up @@ -37,7 +37,7 @@ impl JobTokenServer {
/// compilation.
fn new() -> &'static Self {
// TODO: Replace with a OnceLock once MSRV is 1.70
static JOBSERVER: OnceCell<JobTokenServer> = OnceCell::new();
static JOBSERVER: OnceLock<JobTokenServer> = OnceLock::new();

JOBSERVER.get_or_init(|| {
unsafe { inherited_jobserver::JobServer::from_env() }
Expand All @@ -62,16 +62,16 @@ impl ActiveJobTokenServer {
}
}

pub(crate) async fn acquire(&self) -> Result<JobToken, Error> {
match &self {
pub(crate) async fn acquire(&mut self) -> Result<JobToken, Error> {
match self {
Self::Inherited(jobserver) => jobserver.acquire().await,
Self::InProcess(jobserver) => Ok(jobserver.acquire().await),
}
}
}

mod inherited_jobserver {
use super::{JobToken, OnceCell};
use super::JobToken;

use crate::{parallel::async_executor::YieldOnce, Error, ErrorKind};

Expand Down Expand Up @@ -137,7 +137,7 @@ mod inherited_jobserver {
pub(super) fn enter_active(&self) -> ActiveJobServer<'_> {
ActiveJobServer {
jobserver: self,
helper_thread: OnceCell::new(),
helper_thread: None,
}
}
}
Expand All @@ -163,11 +163,11 @@ mod inherited_jobserver {

pub(crate) struct ActiveJobServer<'a> {
jobserver: &'a JobServer,
helper_thread: OnceCell<HelperThread>,
helper_thread: Option<HelperThread>,
}

impl<'a> ActiveJobServer<'a> {
pub(super) async fn acquire(&self) -> Result<JobToken, Error> {
pub(super) async fn acquire(&mut self) -> Result<JobToken, Error> {
let mut has_requested_token = false;

loop {
Expand All @@ -184,9 +184,12 @@ mod inherited_jobserver {
Ok(None) => YieldOnce::default().await,
Err(err) if err.kind() == io::ErrorKind::Unsupported => {
// Fallback to creating a help thread with blocking acquire
let helper_thread = self
.helper_thread
.get_or_try_init(|| HelperThread::new(self.jobserver))?;
let helper_thread = if let Some(thread) = self.helper_thread.as_ref() {
thread
} else {
self.helper_thread
.insert(HelperThread::new(self.jobserver)?)
};

match helper_thread.rx.try_recv() {
Ok(res) => {
Expand Down
1 change: 1 addition & 0 deletions src/parallel/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub(crate) mod async_executor;
pub(crate) mod job_token;
pub(crate) mod once_lock;
pub(crate) mod stderr;
47 changes: 47 additions & 0 deletions src/parallel/once_lock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::{
cell::UnsafeCell,
marker::PhantomData,
mem::MaybeUninit,
panic::{RefUnwindSafe, UnwindSafe},
sync::Once,
};

pub(crate) struct OnceLock<T> {
once: Once,
value: UnsafeCell<MaybeUninit<T>>,
_marker: PhantomData<T>,
}

impl<T> OnceLock<T> {
pub(crate) const fn new() -> Self {
Self {
once: Once::new(),
value: UnsafeCell::new(MaybeUninit::uninit()),
_marker: PhantomData,
}
}

pub(crate) fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
self.once.call_once(|| {
unsafe { &mut *self.value.get() }.write(f());
});
unsafe { (&*self.value.get()).assume_init_ref() }
}
}

unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
unsafe impl<T: Send> Send for OnceLock<T> {}

impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}

impl<T> Drop for OnceLock<T> {
#[inline]
fn drop(&mut self) {
if self.once.is_completed() {
// SAFETY: The cell is initialized and being dropped, so it can't
// be accessed again.
unsafe { self.value.get_mut().assume_init_drop() };
}
}
}

0 comments on commit af4c928

Please sign in to comment.