makepad/libs/relax/compiler/tests/std/os_thread.rs
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
The JIT that runs makepad apps from source: lexer, front end, type checker,
lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and
warm/cold caches keyed by compiler stamp, provided crates bound late,
startup images, live patching. User-facing name is `makepad run` (binary
`makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal
library name. `makepad check` reports rustc-style diagnostics with rustc
error codes and checks a whole workspace (`--workspace`). Runs on macOS,
Linux, Windows and Android. makepad-remote: one tool schema for apps and the
WM (app/1): grabs, captures, traces, frame profiles and tweaks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

109 lines
3.2 KiB
Rust

// std-os lane: std::thread (differential: os_diff.sh)
use std::cell::{Cell, RefCell};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
thread_local! {
static DEPTH: Cell<u32> = Cell::new(0);
static NAMES: RefCell<Vec<String>> = RefCell::new(Vec::new());
}
fn work(n: u64) -> u64 {
let mut s = 0u64;
let mut i = 0;
while i < n {
s = s.wrapping_mul(31).wrapping_add(i);
i += 1;
}
s
}
#[test]
fn a01_spawn_join() {
let hs: Vec<_> = (1..=4).map(|k| thread::spawn(move || work(k * 1000))).collect();
for h in hs {
println!("| {}", h.join().unwrap());
}
let h = thread::Builder::new().name(String::from("worker-7")).stack_size(256 * 1024).spawn(|| {
let t = thread::current();
format!("{:?}", t.name())
}).unwrap();
println!("| {}", h.join().unwrap());
println!("| {:?}", thread::spawn(|| thread::current().name().map(|s| s.to_string())).join().unwrap());
}
#[test]
fn a02_panic_join() {
let h = thread::spawn(|| {
if work(3) < 100 {
panic!("boom in thread");
}
5
});
let r = h.join();
println!("| {}", r.is_err());
}
#[test]
fn a03_thread_local() {
DEPTH.with(|d| d.set(d.get() + 3));
let h = thread::spawn(|| {
DEPTH.set(10);
NAMES.with_borrow_mut(|v| v.push(String::from("t")));
(DEPTH.get(), NAMES.with_borrow(|v| v.len()))
});
println!("| {:?} {} {}", h.join().unwrap(), DEPTH.get(), NAMES.with_borrow(|v| v.len()));
println!("| {} {}", DEPTH.replace(1), DEPTH.take());
}
#[test]
fn a04_sleep_park() {
let t0 = Instant::now();
thread::sleep(Duration::from_millis(20));
let e = t0.elapsed();
println!("| {}", e >= Duration::from_millis(20) && e < Duration::from_secs(2));
let flag = Arc::new(AtomicUsize::new(0));
let f2 = flag.clone();
let main = thread::current();
let h = thread::spawn(move || {
thread::sleep(Duration::from_millis(5));
f2.store(1, Ordering::SeqCst);
main.unpark();
});
while flag.load(Ordering::SeqCst) == 0 {
thread::park();
}
h.join().unwrap();
println!("| {}", flag.load(Ordering::SeqCst));
let t1 = Instant::now();
thread::park_timeout(Duration::from_millis(10));
println!("| {}", t1.elapsed() < Duration::from_secs(2));
thread::yield_now();
println!("| {}", thread::available_parallelism().unwrap().get() >= 1);
println!("| {}", thread::panicking());
}
#[test]
fn a05_scope() {
let mut data = vec![1, 2, 3, 4];
let total = AtomicUsize::new(0);
thread::scope(|s| {
for x in data.iter() {
let total = &total;
s.spawn(move || {
total.fetch_add(*x, Ordering::SeqCst);
});
}
let h = s.spawn(|| 99);
println!("| {}", h.join().unwrap());
});
data.push(5);
println!("| {} {:?}", total.load(Ordering::SeqCst), data);
let ids: Vec<bool> = (0..3).map(|_| thread::spawn(|| thread::current().id()).join().unwrap() != thread::current().id()).collect();
println!("| {:?}", ids);
let h = thread::spawn(|| thread::sleep(Duration::from_millis(1)));
let _ = h.thread().id();
h.join().unwrap();
}