| use super::id::ThreadId; | |
| use super::main_thread; | |
| use crate::alloc::System; | |
| use crate::ffi::CStr; | |
| use crate::fmt; | |
| use crate::pin::Pin; | |
| use crate::sync::{Arc, OnceLock}; | |
| use crate::sys::sync::Parker; | |
| use crate::sys::thread as imp; | |
| use crate::time::Duration; | |
| // This module ensures private fields are kept private, which is necessary to enforce the safety requirements. | |
| mod thread_name_string { | |
| use crate::ffi::{CStr, CString}; | |
| use crate::str; | |
| /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. | |
| pub(crate) struct ThreadNameString { | |
| inner: CString, | |
| } | |
| impl From<String> for ThreadNameString { | |
| fn from(s: String) -> Self { | |
| Self { | |
| inner: CString::new(s).expect("thread name may not contain interior null bytes"), | |
| } | |
| } | |
| } | |
| impl ThreadNameString { | |
| pub(crate) fn as_cstr(&self) -> &CStr { | |
| &self.inner | |
| } | |
| pub(crate) fn as_str(&self) -> &str { | |
| // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. | |
| unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } | |
| } | |
| } | |
| } | |
| use thread_name_string::ThreadNameString; | |
| /// The internal representation of a `Thread` handle | |
| /// | |
| /// We explicitly set the alignment for our guarantee in Thread::into_raw. This | |
| /// allows applications to stuff extra metadata bits into the alignment, which | |
| /// can be rather useful when working with atomics. | |
| #[repr(align(8))] | |
| struct Inner { | |
| name: Option<ThreadNameString>, | |
| id: ThreadId, | |
| os_id: OnceLock<u64>, | |
| parker: Parker, | |
| } | |
| impl Inner { | |
| fn parker(self: Pin<&Self>) -> Pin<&Parker> { | |
| unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } | |
| } | |
| } | |
| #[derive(Clone)] | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| /// A handle to a thread. | |
| /// | |
| /// Threads are represented via the `Thread` type, which you can get in one of | |
| /// two ways: | |
| /// | |
| /// * By spawning a new thread, e.g., using the [`thread::spawn`] | |
| /// function, and calling [`thread`] on the [`JoinHandle`]. | |
| /// * By requesting the current thread, using the [`thread::current`] function. | |
| /// | |
| /// The [`thread::current`] function is available even for threads not spawned | |
| /// by the APIs of this module. | |
| /// | |
| /// There is usually no need to create a `Thread` struct yourself, one | |
| /// should instead use a function like `spawn` to create new threads, see the | |
| /// docs of [`Builder`] and [`spawn`] for more details. | |
| /// | |
| /// [`thread::spawn`]: super::spawn | |
| /// [`thread`]: super::JoinHandle::thread | |
| /// [`JoinHandle`]: super::JoinHandle | |
| /// [`thread::current`]: super::current::current | |
| /// [`Builder`]: super::Builder | |
| /// [`spawn`]: super::spawn | |
| pub struct Thread { | |
| // We use the System allocator such that creating or dropping this handle | |
| // does not interfere with a potential Global allocator using thread-local | |
| // storage. | |
| inner: Pin<Arc<Inner, System>>, | |
| } | |
| impl Thread { | |
| pub(crate) fn new(id: ThreadId, name: Option<String>) -> Thread { | |
| let name = name.map(ThreadNameString::from); | |
| // We have to use `unsafe` here to construct the `Parker` in-place, | |
| // which is required for the UNIX implementation. | |
| // | |
| // SAFETY: We pin the Arc immediately after creation, so its address never | |
| // changes. | |
| let inner = unsafe { | |
| let mut arc = Arc::<Inner, _>::new_uninit_in(System); | |
| let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); | |
| (&raw mut (*ptr).name).write(name); | |
| (&raw mut (*ptr).id).write(id); | |
| (&raw mut (*ptr).os_id).write(OnceLock::new()); | |
| Parker::new_in_place(&raw mut (*ptr).parker); | |
| Pin::new_unchecked(arc.assume_init()) | |
| }; | |
| Thread { inner } | |
| } | |
| /// Creates a handle for the calling thread, recording its OS id. | |
| /// | |
| /// `id` must be the `ThreadId` of the calling thread. | |
| /// | |
| /// Takes no name because passing one into `Thread::new` allocates with the | |
| /// global allocator, which `thread::current` is documented never to use. | |
| pub(crate) fn new_current(id: ThreadId) -> Thread { | |
| let thread = Thread::new(id, None); | |
| thread.set_os_id_to_current(); | |
| thread | |
| } | |
| /// Records the calling thread's OS id, as reported by | |
| /// `imp::current_os_id`, in this handle. | |
| /// | |
| /// May only be called from the thread to which this handle belongs. A | |
| /// spawned thread does this itself once it starts running, since its handle | |
| /// already exists by then. | |
| /// | |
| /// `imp::current_os_id` must not allocate with the global allocator or call | |
| /// `thread::current`. | |
| pub(crate) fn set_os_id_to_current(&self) { | |
| if let Some(os_id) = imp::current_os_id() { | |
| if self.inner.os_id.set(os_id).is_err() { | |
| rtabort!("thread OS id already set"); | |
| } | |
| } | |
| } | |
| /// Like the public [`park`], 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. | |
| /// | |
| /// [`park`]: super::park | |
| pub(crate) unsafe fn park(&self) { | |
| unsafe { self.inner.as_ref().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. | |
| /// | |
| /// [`park_timeout`]: super::park_timeout | |
| pub(crate) unsafe fn park_timeout(&self, dur: Duration) { | |
| unsafe { self.inner.as_ref().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 | |
| /// the [`park`] function and the `unpark()` method. These can be used as a | |
| /// more CPU-efficient implementation of a spinlock. | |
| /// | |
| /// See the [park documentation] for more details. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// use std::time::Duration; | |
| /// use std::sync::atomic::{AtomicBool, Ordering}; | |
| /// | |
| /// static QUEUED: AtomicBool = AtomicBool::new(false); | |
| /// | |
| /// let parked_thread = thread::Builder::new() | |
| /// .spawn(|| { | |
| /// println!("Parking thread"); | |
| /// QUEUED.store(true, Ordering::Release); | |
| /// thread::park(); | |
| /// println!("Thread unparked"); | |
| /// }) | |
| /// .unwrap(); | |
| /// | |
| /// // Let some time pass for the thread to be spawned. | |
| /// thread::sleep(Duration::from_millis(10)); | |
| /// | |
| /// // Wait until the other thread is queued. | |
| /// // This is crucial! It guarantees that the `unpark` below is not consumed | |
| /// // by some other code in the parked thread (e.g. inside `println!`). | |
| /// while !QUEUED.load(Ordering::Acquire) { | |
| /// // Spinning is of course inefficient; in practice, this would more likely be | |
| /// // a dequeue where we have no work to do if there's nobody queued. | |
| /// std::hint::spin_loop(); | |
| /// } | |
| /// | |
| /// println!("Unpark the thread"); | |
| /// parked_thread.thread().unpark(); | |
| /// | |
| /// parked_thread.join().unwrap(); | |
| /// ``` | |
| /// | |
| /// [`park`]: super::park | |
| /// [park documentation]: super::park | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[inline] | |
| pub fn unpark(&self) { | |
| self.inner.as_ref().parker().unpark(); | |
| } | |
| /// Gets the thread's unique identifier. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let other_thread = thread::spawn(|| { | |
| /// thread::current().id() | |
| /// }); | |
| /// | |
| /// let other_thread_id = other_thread.join().unwrap(); | |
| /// assert!(thread::current().id() != other_thread_id); | |
| /// ``` | |
| #[stable(feature = "thread_id", since = "1.19.0")] | |
| #[must_use] | |
| pub fn id(&self) -> ThreadId { | |
| self.inner.id | |
| } | |
| /// Gets the id the operating system gave this thread, if it has one that can | |
| /// be read. | |
| /// | |
| /// This is the id that shows up in tools like `ps` and `top`, debuggers and | |
| /// crash logs, unlike [`ThreadId`], which has no guaranteed relationship to | |
| /// it. On a platform with no OS-visible thread id, such as SGX, the value | |
| /// may be some other per-thread value (there, the thread's address), which | |
| /// such tools will not recognize. `None` means no id could be recorded: the | |
| /// thread has not started running yet, or the platform has no way to read | |
| /// one. | |
| /// | |
| /// The operating system may reuse the id of a thread that has exited, and a | |
| /// `Thread` handle can outlive the thread it refers to. After a `fork`, the | |
| /// id recorded in the child process still refers to the parent's thread; it | |
| /// is not re-read. Use the id only where a reused or stale id is harmless, | |
| /// such as logging. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// #![feature(thread_os_id)] | |
| /// use std::thread; | |
| /// | |
| /// let spawned = thread::spawn(|| thread::current().os_id()).join().unwrap(); | |
| /// if spawned.is_some() { | |
| /// assert_ne!(spawned, thread::current().os_id()); | |
| /// } | |
| /// ``` | |
| #[unstable(feature = "thread_os_id", issue = "160215")] | |
| #[must_use] | |
| pub fn os_id(&self) -> Option<u64> { | |
| self.inner.os_id.get().copied() | |
| } | |
| /// Gets the thread's name. | |
| /// | |
| /// For more information about named threads, see | |
| /// [this module-level documentation][naming-threads]. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Threads by default have no name specified: | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new(); | |
| /// | |
| /// let handler = builder.spawn(|| { | |
| /// assert!(thread::current().name().is_none()); | |
| /// }).unwrap(); | |
| /// | |
| /// handler.join().unwrap(); | |
| /// ``` | |
| /// | |
| /// Thread with a specified name: | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new() | |
| /// .name("foo".into()); | |
| /// | |
| /// let handler = builder.spawn(|| { | |
| /// assert_eq!(thread::current().name(), Some("foo")) | |
| /// }).unwrap(); | |
| /// | |
| /// handler.join().unwrap(); | |
| /// ``` | |
| /// | |
| /// [naming-threads]: ./index.html#naming-threads | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[must_use] | |
| pub fn name(&self) -> Option<&str> { | |
| if let Some(name) = &self.inner.name { | |
| Some(name.as_str()) | |
| } else if main_thread::get() == Some(self.inner.id) { | |
| Some("main") | |
| } else { | |
| None | |
| } | |
| } | |
| /// Consumes the `Thread`, returning a raw pointer. | |
| /// | |
| /// To avoid a memory leak the pointer must be converted | |
| /// back into a `Thread` using [`Thread::from_raw`]. The pointer is | |
| /// guaranteed to be aligned to at least 8 bytes. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// #![feature(thread_raw)] | |
| /// | |
| /// use std::thread::{self, Thread}; | |
| /// | |
| /// let thread = thread::current(); | |
| /// let id = thread.id(); | |
| /// let ptr = Thread::into_raw(thread); | |
| /// unsafe { | |
| /// assert_eq!(Thread::from_raw(ptr).id(), id); | |
| /// } | |
| /// ``` | |
| #[unstable(feature = "thread_raw", issue = "97523")] | |
| pub fn into_raw(self) -> *const () { | |
| // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. | |
| let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; | |
| Arc::into_raw_with_allocator(inner).0 as *const () | |
| } | |
| /// Constructs a `Thread` from a raw pointer. | |
| /// | |
| /// The raw pointer must have been previously returned | |
| /// by a call to [`Thread::into_raw`]. | |
| /// | |
| /// # Safety | |
| /// | |
| /// This function is unsafe because improper use may lead | |
| /// to memory unsafety, even if the returned `Thread` is never | |
| /// accessed. | |
| /// | |
| /// Creating a `Thread` from a pointer other than one returned | |
| /// from [`Thread::into_raw`] is **undefined behavior**. | |
| /// | |
| /// Calling this function twice on the same raw pointer can lead | |
| /// to a double-free if both `Thread` instances are dropped. | |
| #[unstable(feature = "thread_raw", issue = "97523")] | |
| pub unsafe fn from_raw(ptr: *const ()) -> Thread { | |
| // Safety: Upheld by caller. | |
| unsafe { | |
| Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } | |
| } | |
| } | |
| pub(crate) fn cname(&self) -> Option<&CStr> { | |
| if let Some(name) = &self.inner.name { | |
| Some(name.as_cstr()) | |
| } else if main_thread::get() == Some(self.inner.id) { | |
| Some(c"main") | |
| } else { | |
| None | |
| } | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl fmt::Debug for Thread { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| f.debug_struct("Thread") | |
| .field("id", &self.id()) | |
| .field("name", &self.name()) | |
| .finish_non_exhaustive() | |
| } | |
| } |