Struct Thread

pub struct Thread { pub(in ::thread::thread) inner: Pin<Arc<Inner, System>> }

A handle to a thread.

Threads are represented via the Thread type, which you can get in one of two ways:

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.

Fields

inner: Pin<Arc<Inner, System>>

Implementations

impl Thread

fn new(id: ThreadId, name: Option<String>) -> Thread
fn new_current(id: ThreadId) -> Thread

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.

fn set_os_id_to_current(&self)

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.

unsafe fn park(&self)

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.

unsafe fn park_timeout(&self, dur: Duration)

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.

fn unpark(&self)

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();
fn id(&self) -> ThreadId

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);
fn os_id(&self) -> Option<u64>

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());
}
fn name(&self) -> Option<&str>

Gets the thread's name.

For more information about named threads, see this module-level documentation.

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();
fn into_raw(self) -> *const ()

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);
}
unsafe fn from_raw(ptr: *const ()) -> Thread

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.

fn cname(&self) -> Option<&CStr>

Trait Implementations

impl Clone for Thread

fn clone(&self) -> Self

impl Debug for Thread

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Auto Trait Implementations

impl Freeze for Thread

impl RefUnwindSafe for Thread

impl Send for Thread

impl Sync for Thread

impl Unpin for Thread

impl UnsafeUnpin for Thread

impl UnwindSafe for Thread

Blanket Implementations

impl<T> Any for Thread where T: 'static + ?Sized,

fn type_id(&self) -> TypeId

impl<T> Borrow<T> for Thread where T: ?Sized,

fn borrow(&self) -> &T

impl<T> BorrowMut<T> for Thread where T: ?Sized,

fn borrow_mut(&mut self) -> &mut T

impl<T> CloneToUninit for Thread where T: Clone,

unsafe fn clone_to_uninit(&self, dest: *mut u8)

impl<T> From<T> for Thread

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> SizeHint for Thread where T: ?Sized,

fn lower_bound(&self) -> usize
fn upper_bound(&self) -> Option<usize>

impl<T> SizedTypeProperties for Thread

impl<T> ToOwned for Thread where T: Clone,

type Owned = T;
fn to_owned(&self) -> T
fn clone_into(&self, target: &mut T)

impl<T, U> Into<U> for Thread where U: From<T>,

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom<U> for Thread where U: Into<T>,

type Error = never;
fn try_from(value: U) -> Result<T, never>

impl<T, U> TryInto<U> for Thread where U: TryFrom<T>,

type Error = <U as TryFrom<T>>::Error;
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>