diff options
Diffstat (limited to 'library/std/src/thread')
| -rw-r--r-- | library/std/src/thread/current.rs | 17 | ||||
| -rw-r--r-- | library/std/src/thread/mod.rs | 15 | ||||
| -rw-r--r-- | library/std/src/thread/scoped.rs | 7 |
3 files changed, 33 insertions, 6 deletions
diff --git a/library/std/src/thread/current.rs b/library/std/src/thread/current.rs index e6eb90c4c30..b9b959f9894 100644 --- a/library/std/src/thread/current.rs +++ b/library/std/src/thread/current.rs @@ -165,6 +165,23 @@ pub(crate) fn try_current() -> Option<Thread> { } } +/// Gets a handle to the thread that invokes it. If the handle stored in thread- +/// local storage was already destroyed, this creates a new unnamed temporary +/// handle to allow thread parking in nearly all situations. +pub(crate) fn current_or_unnamed() -> Thread { + let current = CURRENT.get(); + if current > DESTROYED { + unsafe { + let current = ManuallyDrop::new(Thread::from_raw(current)); + (*current).clone() + } + } else if current == DESTROYED { + Thread::new_unnamed(id::get_or_init()) + } else { + init_current(current) + } +} + /// Gets a handle to the thread that invokes it. /// /// # Examples diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 2c2cc58a9dd..2ff44fcd4c6 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -186,7 +186,7 @@ mod current; #[stable(feature = "rust1", since = "1.0.0")] pub use current::current; -pub(crate) use current::{current_id, drop_current, set_current, try_current}; +pub(crate) use current::{current_id, current_or_unnamed, drop_current, set_current, try_current}; mod spawnhook; @@ -1146,9 +1146,9 @@ pub fn park_timeout_ms(ms: u32) { #[stable(feature = "park_timeout", since = "1.4.0")] pub fn park_timeout(dur: Duration) { let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. + // SAFETY: park_timeout is called on a handle owned by this thread. unsafe { - current().0.parker().park_timeout(dur); + current().park_timeout(dur); } // No panic occurred, do not abort. forget(guard); @@ -1446,6 +1446,15 @@ impl Thread { unsafe { self.0.parker().park() } } + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.0.parker().park_timeout(dur) } + } + /// Atomically makes the handle's token available if it is not already. /// /// Every thread is equipped with some basic low-level blocking support, via diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index a14446b3515..0033fc3a732 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -1,4 +1,4 @@ -use super::{Builder, JoinInner, Result, Thread, current, park}; +use super::{Builder, JoinInner, Result, Thread, current_or_unnamed}; use crate::marker::PhantomData; use crate::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; use crate::sync::Arc; @@ -140,7 +140,7 @@ where let scope = Scope { data: Arc::new(ScopeData { num_running_threads: AtomicUsize::new(0), - main_thread: current(), + main_thread: current_or_unnamed(), a_thread_panicked: AtomicBool::new(false), }), env: PhantomData, @@ -152,7 +152,8 @@ where // Wait until all the threads are finished. while scope.data.num_running_threads.load(Ordering::Acquire) != 0 { - park(); + // SAFETY: this is the main thread, the handle belongs to us. + unsafe { scope.data.main_thread.park() }; } // Throw any panic from `f`, or the return value of `f` if no thread panicked. |
