Skip to content

Commit f6b72b0

Browse files
committed
Fix cyclic compilation: Use vendored once_cell
Fix #1146
1 parent 25bee03 commit f6b72b0

File tree

4 files changed

+74
-7
lines changed

4 files changed

+74
-7
lines changed

Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@ rust-version = "1.67"
2121

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

2625
[target.'cfg(unix)'.dependencies]
2726
# Don't turn on the feature "std" for this, see https://github.com/rust-lang/cargo/issues/4866
2827
# which is still an issue with `resolver = "1"`.
2928
libc = { version = "0.2.62", default-features = false, optional = true }
3029

3130
[features]
32-
parallel = ["dep:libc", "dep:jobserver", "dep:once_cell"]
31+
parallel = ["dep:libc", "dep:jobserver"]
3332
# This is a placeholder feature for people who incorrectly used `cc` with `features = ["jobserver"]`
3433
# so that they aren't broken. This has never enabled `parallel`, so we won't do that.
3534
jobserver = []

src/parallel/job_token.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::marker::PhantomData;
22

33
use crate::Error;
44

5-
use once_cell::sync::OnceCell;
5+
use super::once_cell::OnceCell;
66

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

@@ -163,7 +163,7 @@ mod inherited_jobserver {
163163

164164
pub(crate) struct ActiveJobServer<'a> {
165165
jobserver: &'a JobServer,
166-
helper_thread: OnceCell<HelperThread>,
166+
helper_thread: OnceCell<Option<HelperThread>>,
167167
}
168168

169169
impl<'a> ActiveJobServer<'a> {
@@ -183,10 +183,30 @@ mod inherited_jobserver {
183183
}
184184
Ok(None) => YieldOnce::default().await,
185185
Err(err) if err.kind() == io::ErrorKind::Unsupported => {
186+
let mut err = None;
186187
// Fallback to creating a help thread with blocking acquire
187-
let helper_thread = self
188-
.helper_thread
189-
.get_or_try_init(|| HelperThread::new(self.jobserver))?;
188+
let helper_thread = self.helper_thread.get_or_init(|| {
189+
match HelperThread::new(self.jobserver) {
190+
Ok(thread) => Some(thread),
191+
Err(error) => {
192+
err = Some(error);
193+
None
194+
}
195+
}
196+
});
197+
198+
if let Some(err) = err {
199+
return Err(err.into());
200+
}
201+
202+
let helper_thread = if let Some(thread) = helper_thread {
203+
thread
204+
} else {
205+
return Err(Error::new(
206+
ErrorKind::JobserverHelpThreadError,
207+
"Creation failed",
208+
));
209+
};
190210

191211
match helper_thread.rx.try_recv() {
192212
Ok(res) => {

src/parallel/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub(crate) mod async_executor;
22
pub(crate) mod job_token;
3+
pub(crate) mod once_cell;
34
pub(crate) mod stderr;

src/parallel/once_cell.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use std::{
2+
cell::UnsafeCell,
3+
marker::PhantomData,
4+
mem::MaybeUninit,
5+
panic::{RefUnwindSafe, UnwindSafe},
6+
sync::Once,
7+
};
8+
9+
pub(crate) struct OnceCell<T> {
10+
once: Once,
11+
value: UnsafeCell<MaybeUninit<T>>,
12+
_marker: PhantomData<T>,
13+
}
14+
15+
impl<T> OnceCell<T> {
16+
pub(crate) const fn new() -> Self {
17+
Self {
18+
once: Once::new(),
19+
value: UnsafeCell::new(MaybeUninit::uninit()),
20+
_marker: PhantomData,
21+
}
22+
}
23+
24+
pub(crate) fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
25+
self.once.call_once_force(|_| {
26+
unsafe { &mut *self.value.get() }.write(f());
27+
});
28+
unsafe { (&*self.value.get()).assume_init_ref() }
29+
}
30+
}
31+
32+
unsafe impl<T: Sync + Send> Sync for OnceCell<T> {}
33+
unsafe impl<T: Send> Send for OnceCell<T> {}
34+
35+
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {}
36+
impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {}
37+
38+
impl<T> Drop for OnceCell<T> {
39+
#[inline]
40+
fn drop(&mut self) {
41+
if self.once.is_completed() {
42+
// SAFETY: The cell is initialized and being dropped, so it can't
43+
// be accessed again.
44+
unsafe { (&mut *self.value.get()).assume_init_drop() };
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)