Skip to content

Commit 4553772

Browse files
committed
std: replace LazyBox with OnceBox
This PR replaces the `LazyBox` wrapper used to allocate the pthread primitives with `OnceBox`, which has a more familiar API mirroring that of `OnceLock`. This cleans up the code in preparation for larger changes like #128184 (from which this PR was split) and allows some neat optimizations, like avoid an acquire-load of the allocation pointer in `Mutex::unlock`, where the initialization of the allocation must have already been observed. Additionally, I've gotten rid of the TEEOS `Condvar` code, it's just a duplicate of the pthread one anyway and I didn't want to repeat myself.
1 parent 21aa500 commit 4553772

File tree

12 files changed

+185
-284
lines changed

12 files changed

+185
-284
lines changed

library/std/src/sys/sync/condvar/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ cfg_if::cfg_if! {
1212
))] {
1313
mod futex;
1414
pub use futex::Condvar;
15-
} else if #[cfg(target_family = "unix")] {
15+
} else if #[cfg(any(
16+
target_family = "unix",
17+
target_os = "teeos",
18+
))] {
1619
mod pthread;
1720
pub use pthread::Condvar;
1821
} else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
@@ -24,9 +27,6 @@ cfg_if::cfg_if! {
2427
} else if #[cfg(target_os = "solid_asp3")] {
2528
mod itron;
2629
pub use itron::Condvar;
27-
} else if #[cfg(target_os = "teeos")] {
28-
mod teeos;
29-
pub use teeos::Condvar;
3030
} else if #[cfg(target_os = "xous")] {
3131
mod xous;
3232
pub use xous::Condvar;

library/std/src/sys/sync/condvar/pthread.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,25 @@ use crate::cell::UnsafeCell;
22
use crate::ptr;
33
use crate::sync::atomic::AtomicPtr;
44
use crate::sync::atomic::Ordering::Relaxed;
5-
use crate::sys::sync::{Mutex, mutex};
5+
use crate::sys::sync::{Mutex, OnceBox};
66
#[cfg(not(target_os = "nto"))]
77
use crate::sys::time::TIMESPEC_MAX;
88
#[cfg(target_os = "nto")]
99
use crate::sys::time::TIMESPEC_MAX_CAPPED;
10-
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
1110
use crate::time::Duration;
1211

1312
struct AllocatedCondvar(UnsafeCell<libc::pthread_cond_t>);
1413

1514
pub struct Condvar {
16-
inner: LazyBox<AllocatedCondvar>,
15+
inner: OnceBox<AllocatedCondvar>,
1716
mutex: AtomicPtr<libc::pthread_mutex_t>,
1817
}
1918

20-
#[inline]
21-
fn raw(c: &Condvar) -> *mut libc::pthread_cond_t {
22-
c.inner.0.get()
23-
}
24-
2519
unsafe impl Send for AllocatedCondvar {}
2620
unsafe impl Sync for AllocatedCondvar {}
2721

28-
impl LazyInit for AllocatedCondvar {
29-
fn init() -> Box<Self> {
22+
impl AllocatedCondvar {
23+
fn new() -> Box<Self> {
3024
let condvar = Box::new(AllocatedCondvar(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER)));
3125

3226
cfg_if::cfg_if! {
@@ -37,7 +31,7 @@ impl LazyInit for AllocatedCondvar {
3731
target_vendor = "apple",
3832
))] {
3933
// `pthread_condattr_setclock` is unfortunately not supported on these platforms.
40-
} else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
34+
} else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "teeos"))] {
4135
// NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet
4236
// So on that platform, init() should always be called
4337
// Moreover, that platform does not have pthread_condattr_setclock support,
@@ -82,7 +76,11 @@ impl Drop for AllocatedCondvar {
8276

8377
impl Condvar {
8478
pub const fn new() -> Condvar {
85-
Condvar { inner: LazyBox::new(), mutex: AtomicPtr::new(ptr::null_mut()) }
79+
Condvar { inner: OnceBox::new(), mutex: AtomicPtr::new(ptr::null_mut()) }
80+
}
81+
82+
fn get(&self) -> *mut libc::pthread_cond_t {
83+
self.inner.get_or_init(AllocatedCondvar::new).0.get()
8684
}
8785

8886
#[inline]
@@ -98,21 +96,21 @@ impl Condvar {
9896

9997
#[inline]
10098
pub fn notify_one(&self) {
101-
let r = unsafe { libc::pthread_cond_signal(raw(self)) };
99+
let r = unsafe { libc::pthread_cond_signal(self.get()) };
102100
debug_assert_eq!(r, 0);
103101
}
104102

105103
#[inline]
106104
pub fn notify_all(&self) {
107-
let r = unsafe { libc::pthread_cond_broadcast(raw(self)) };
105+
let r = unsafe { libc::pthread_cond_broadcast(self.get()) };
108106
debug_assert_eq!(r, 0);
109107
}
110108

111109
#[inline]
112110
pub unsafe fn wait(&self, mutex: &Mutex) {
113-
let mutex = mutex::raw(mutex);
111+
let mutex = mutex.get_assert_locked();
114112
self.verify(mutex);
115-
let r = libc::pthread_cond_wait(raw(self), mutex);
113+
let r = libc::pthread_cond_wait(self.get(), mutex);
116114
debug_assert_eq!(r, 0);
117115
}
118116

@@ -129,7 +127,7 @@ impl Condvar {
129127
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
130128
use crate::sys::time::Timespec;
131129

132-
let mutex = mutex::raw(mutex);
130+
let mutex = mutex.get_assert_locked();
133131
self.verify(mutex);
134132

135133
#[cfg(not(target_os = "nto"))]
@@ -144,7 +142,7 @@ impl Condvar {
144142
.and_then(|t| t.to_timespec_capped())
145143
.unwrap_or(TIMESPEC_MAX_CAPPED);
146144

147-
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
145+
let r = libc::pthread_cond_timedwait(self.get(), mutex, &timeout);
148146
assert!(r == libc::ETIMEDOUT || r == 0);
149147
r == 0
150148
}
@@ -162,7 +160,7 @@ impl Condvar {
162160
use crate::sys::time::SystemTime;
163161
use crate::time::Instant;
164162

165-
let mutex = mutex::raw(mutex);
163+
let mutex = mutex.get_assert_locked();
166164
self.verify(mutex);
167165

168166
// OSX implementation of `pthread_cond_timedwait` is buggy
@@ -188,7 +186,7 @@ impl Condvar {
188186
.and_then(|t| t.to_timespec())
189187
.unwrap_or(TIMESPEC_MAX);
190188

191-
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
189+
let r = libc::pthread_cond_timedwait(self.get(), mutex, &timeout);
192190
debug_assert!(r == libc::ETIMEDOUT || r == 0);
193191

194192
// ETIMEDOUT is not a totally reliable method of determining timeout due

library/std/src/sys/sync/condvar/sgx.rs

+12-17
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,39 @@
11
use crate::sys::pal::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
2-
use crate::sys::sync::Mutex;
3-
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
2+
use crate::sys::sync::{Mutex, OnceBox};
43
use crate::time::Duration;
54

6-
/// FIXME: `UnsafeList` is not movable.
7-
struct AllocatedCondvar(SpinMutex<WaitVariable<()>>);
8-
95
pub struct Condvar {
10-
inner: LazyBox<AllocatedCondvar>,
11-
}
12-
13-
impl LazyInit for AllocatedCondvar {
14-
fn init() -> Box<Self> {
15-
Box::new(AllocatedCondvar(SpinMutex::new(WaitVariable::new(()))))
16-
}
6+
// FIXME: `UnsafeList` is not movable.
7+
inner: OnceBox<SpinMutex<WaitVariable<()>>>,
178
}
189

1910
impl Condvar {
2011
pub const fn new() -> Condvar {
21-
Condvar { inner: LazyBox::new() }
12+
Condvar { inner: OnceBox::new() }
13+
}
14+
15+
fn get(&self) -> &SpinMutex<WaitVariable<()>> {
16+
self.inner.get_or_init(|| Box::new(SpinMutex::new(WaitVariable::new(()))))
2217
}
2318

2419
#[inline]
2520
pub fn notify_one(&self) {
26-
let _ = WaitQueue::notify_one(self.inner.0.lock());
21+
let _ = WaitQueue::notify_one(self.get().lock());
2722
}
2823

2924
#[inline]
3025
pub fn notify_all(&self) {
31-
let _ = WaitQueue::notify_all(self.inner.0.lock());
26+
let _ = WaitQueue::notify_all(self.get().lock());
3227
}
3328

3429
pub unsafe fn wait(&self, mutex: &Mutex) {
35-
let guard = self.inner.0.lock();
30+
let guard = self.get().lock();
3631
WaitQueue::wait(guard, || unsafe { mutex.unlock() });
3732
mutex.lock()
3833
}
3934

4035
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
41-
let success = WaitQueue::wait_timeout(&self.inner.0, dur, || unsafe { mutex.unlock() });
36+
let success = WaitQueue::wait_timeout(self.get(), dur, || unsafe { mutex.unlock() });
4237
mutex.lock();
4338
success
4439
}

library/std/src/sys/sync/condvar/teeos.rs

-101
This file was deleted.

library/std/src/sys/sync/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
mod condvar;
22
mod mutex;
33
mod once;
4+
mod once_box;
45
mod rwlock;
56
mod thread_parking;
67

78
pub use condvar::Condvar;
89
pub use mutex::Mutex;
910
pub use once::{Once, OnceState};
11+
#[allow(unused)] // Only used on some platforms.
12+
use once_box::OnceBox;
1013
pub use rwlock::RwLock;
1114
pub use thread_parking::Parker;

library/std/src/sys/sync/mutex/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ cfg_if::cfg_if! {
1919
target_os = "teeos",
2020
))] {
2121
mod pthread;
22-
pub use pthread::{Mutex, raw};
22+
pub use pthread::Mutex;
2323
} else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
2424
mod windows7;
2525
pub use windows7::{Mutex, raw};

0 commit comments

Comments
 (0)