Skip to content
9 changes: 9 additions & 0 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,15 @@ impl<T> JoinHandle<T> {
pub fn join(mut self) -> Result<T> {
self.0.join()
}

/// Checks if the the associated thread is still running its main function.
///
/// This might return `false` for a brief moment after the thread's main
/// function has returned, but before the thread itself has stopped running.
#[unstable(feature = "thread_is_running", issue = "90470")]
pub fn is_running(&self) -> bool {
Arc::strong_count(&self.0.packet.0) > 1
}
}

impl<T> AsInner<imp::Thread> for JoinHandle<T> {
Expand Down
36 changes: 35 additions & 1 deletion library/std/src/thread/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ use super::Builder;
use crate::any::Any;
use crate::mem;
use crate::result;
use crate::sync::mpsc::{channel, Sender};
use crate::sync::{
mpsc::{channel, Sender},
Arc, Barrier,
};
use crate::thread::{self, ThreadId};
use crate::time::Duration;
use crate::time::Instant;

// !!! These tests are dangerous. If something is buggy, they will hang, !!!
// !!! instead of exiting cleanly. This might wedge the buildbots. !!!
Expand Down Expand Up @@ -46,6 +50,36 @@ fn test_run_basic() {
rx.recv().unwrap();
}

#[test]
fn test_is_running() {
let b = Arc::new(Barrier::new(2));
let t = thread::spawn({
let b = b.clone();
move || {
b.wait();
1234
}
});

// Thread is definitely running here, since it's still waiting for the barrier.
assert_eq!(t.is_running(), true);

// Unblock the barrier.
b.wait();

// Now check that t.is_running() becomes false within a reasonable time.
let start = Instant::now();
while t.is_running() {
assert!(start.elapsed() < Duration::from_secs(2));
thread::sleep(Duration::from_millis(15));
}

// Joining the thread should not block for a significant time now.
let join_time = Instant::now();
assert_eq!(t.join().unwrap(), 1234);
assert!(join_time.elapsed() < Duration::from_secs(2));
}

#[test]
fn test_join_panic() {
match thread::spawn(move || panic!()).join() {
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ impl<'a> Builder<'a> {
doc::RustByExample,
doc::RustcBook,
doc::CargoBook,
doc::Clippy,
doc::EmbeddedBook,
doc::EditionGuide,
),
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ tool_doc!(
"src/tools/rustfmt",
["rustfmt-nightly", "rustfmt-config_proc_macro"],
);
tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]);

#[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex {
Expand Down
2 changes: 1 addition & 1 deletion src/doc/unstable-book/src/library-features/asm.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ unsafe {
}

println!(
"L1 Cache: {}",
"L0 Cache: {}",
((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)
);
```
Expand Down
2 changes: 1 addition & 1 deletion src/tools/rust-analyzer