/// execution. The signal is sent once all TLS destructors have finished at
/// which point no new thread locals should be created.
pub mod wait_notify {
- use crate::mem::MaybeUninit;
use crate::pin::Pin;
use crate::sync::Arc;
use crate::sys_common::thread_parking::Parker;
/// called, this will return immediately, otherwise the current thread
/// is blocked until notified.
pub fn wait(self) {
- // This is not actually `unsafe`, but it uses the `Parker` API,
- // which needs `unsafe` on some platforms.
+ // SAFETY:
+ // This is only ever called on one thread.
unsafe { Pin::new(&*self.0).park() }
}
}
pub fn new() -> (Notifier, Waiter) {
- // Safety:
- // Some other platforms (looking at you, UNIX!) require that the thread
- // parker is constructed in-place. This is just a noisy way of writing:
- // ```rust
- // let parker = Parker::new();
- // ```
- let parker = unsafe {
- let mut place = MaybeUninit::uninit();
- Parker::new(place.as_mut_ptr());
- place.assume_init()
- };
- let inner = Arc::new(parker);
+ let inner = Arc::new(Parker::new());
(Notifier(inner.clone()), Waiter(inner))
}
}
unsafe impl Send for Parker {}
impl Parker {
- pub unsafe fn new(parker: *mut Parker) {
+ pub unsafe fn new_in_place(parker: *mut Parker) {
let semaphore = dispatch_semaphore_create(0);
assert!(
!semaphore.is_null(),
///
/// # Safety
/// The constructed parker must never be moved.
- pub unsafe fn new(parker: *mut Parker) {
+ pub unsafe fn new_in_place(parker: *mut Parker) {
// Use the default mutex implementation to allow for simpler initialization.
// This could lead to undefined behaviour when deadlocking. This is avoided
// by not deadlocking. Note in particular the unlocking operation before any
impl Parker {
/// Construct the Windows parker. The UNIX parker implementation
/// requires this to happen in-place.
- pub unsafe fn new(parker: *mut Parker) {
+ pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Self { state: AtomicI8::new(EMPTY) });
}
impl Parker {
/// Construct the futex parker. The UNIX parker implementation
/// requires this to happen in-place.
- pub unsafe fn new(parker: *mut Parker) {
+ pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Self { state: AtomicU32::new(EMPTY) });
}
impl Parker {
/// Construct the generic parker. The UNIX parker implementation
/// requires this to happen in-place.
- pub unsafe fn new(parker: *mut Parker) {
+ pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Parker {
state: AtomicUsize::new(EMPTY),
lock: Mutex::new(()),
const NOTIFIED: i8 = 1;
impl Parker {
+ pub fn new() -> Parker {
+ Parker { state: AtomicI8::new(EMPTY), tid: UnsafeCell::new(None) }
+ }
+
/// Create a new thread parker. UNIX requires this to happen in-place.
- pub unsafe fn new(parker: *mut Parker) {
- parker.write(Parker { state: AtomicI8::new(EMPTY), tid: UnsafeCell::new(None) })
+ pub unsafe fn new_in_place(parker: *mut Parker) {
+ parker.write(Parker::new())
}
/// # Safety
impl Parker {
/// Construct a parker for the current thread. The UNIX parker
/// implementation requires this to happen in-place.
- pub unsafe fn new(parker: *mut Parker) {
+ pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Parker { state: AtomicI8::new(EMPTY), wait_flag: WaitFlag::new() })
}
let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr();
addr_of_mut!((*ptr).name).write(name);
addr_of_mut!((*ptr).id).write(ThreadId::new());
- Parker::new(addr_of_mut!((*ptr).parker));
+ Parker::new_in_place(addr_of_mut!((*ptr).parker));
Pin::new_unchecked(arc.assume_init())
};