diff options
| author | 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> | 2024-11-25 00:39:03 +0800 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-25 00:39:03 +0800 | 
| commit | 31b4023e24e82c7c0ca6b9637de1b14d46d02b92 (patch) | |
| tree | 6151658caf22a6b98e10c622d684094c5492fdc6 /library/std/src/sys/sync/once/queue.rs | |
| parent | f5d18576856ef45d1e47de79889ae7db9d1afa29 (diff) | |
| parent | 5a856b82f3a1bf335e0e62d92c800d8436977af1 (diff) | |
| download | rust-31b4023e24e82c7c0ca6b9637de1b14d46d02b92.tar.gz rust-31b4023e24e82c7c0ca6b9637de1b14d46d02b92.zip | |
Rollup merge of #132730 - joboet:after_main_sync, r=Noratrieb
std: allow after-main use of synchronization primitives By creating an unnamed thread handle when the actual one has already been destroyed, synchronization primitives using thread parking can be used even outside the Rust runtime. This also fixes an inefficiency in the queue-based `RwLock`: if `thread::current` was not initialized yet, it will create a new handle on every parking attempt without initializing `thread::current`. The private `current_or_unnamed` function introduced here fixes this.
Diffstat (limited to 'library/std/src/sys/sync/once/queue.rs')
| -rw-r--r-- | library/std/src/sys/sync/once/queue.rs | 9 | 
1 files changed, 5 insertions, 4 deletions
| diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index 177d0d7744a..87837915b39 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -93,7 +93,7 @@ const QUEUE_MASK: usize = !STATE_MASK; // use interior mutability. #[repr(align(4))] // Ensure the two lower bits are free to use as state bits. struct Waiter { - thread: Cell<Option<Thread>>, + thread: Thread, signaled: AtomicBool, next: Cell<*const Waiter>, } @@ -238,7 +238,7 @@ fn wait( return_on_poisoned: bool, ) -> StateAndQueue { let node = &Waiter { - thread: Cell::new(Some(thread::current())), + thread: thread::current_or_unnamed(), signaled: AtomicBool::new(false), next: Cell::new(ptr::null()), }; @@ -277,7 +277,8 @@ fn wait( // can park ourselves, the result could be this thread never gets // unparked. Luckily `park` comes with the guarantee that if it got // an `unpark` just before on an unparked thread it does not park. - thread::park(); + // SAFETY: we retrieved this handle on the current thread above. + unsafe { node.thread.park() } } return state_and_queue.load(Acquire); @@ -309,7 +310,7 @@ impl Drop for WaiterQueue<'_> { let mut queue = to_queue(current); while !queue.is_null() { let next = (*queue).next.get(); - let thread = (*queue).thread.take().unwrap(); + let thread = (*queue).thread.clone(); (*queue).signaled.store(true, Release); thread.unpark(); queue = next; | 
