makepad/libs/relax/compiler/tests/live/recursion/v1.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

59 lines
1.8 KiB
Rust

// 3.1 / 3.3: patching a recursive fn while frames of it are on another thread's stack.
// Each run releases the thread the previous run left parked at the bottom of a 100-deep
// recursion and prints its result, then parks a new one. Frames on the stack across an edit
// finish in the code they started in; fresh calls run the new body.
// v0: level k adds k, v1: 2k, v2: 3k (1+..+100 = 5050)
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::Mutex;
static PARKED: AtomicBool = AtomicBool::new(false);
static GO: AtomicBool = AtomicBool::new(false);
static DONE: AtomicBool = AtomicBool::new(false);
static RESULT: AtomicU64 = AtomicU64::new(0);
static HAVE: Mutex<bool> = Mutex::new(false);
fn bottom(hold: bool) {
if hold {
PARKED.store(true, Ordering::SeqCst);
while !GO.load(Ordering::SeqCst) {
std::thread::sleep(std::time::Duration::from_millis(1));
}
}
}
fn rec(n: u64, hold: bool) -> u64 {
if n == 0 {
bottom(hold);
return 0;
}
rec(n - 1, hold) + 2 * n
}
fn park_one() {
PARKED.store(false, Ordering::SeqCst);
GO.store(false, Ordering::SeqCst);
DONE.store(false, Ordering::SeqCst);
std::thread::spawn(|| {
let r = rec(100, true);
RESULT.store(r, Ordering::SeqCst);
DONE.store(true, Ordering::SeqCst);
});
while !PARKED.load(Ordering::SeqCst) {
std::thread::sleep(std::time::Duration::from_millis(1));
}
}
#[test]
fn run() {
let mut have = HAVE.lock().unwrap();
if *have {
GO.store(true, Ordering::SeqCst);
while !DONE.load(Ordering::SeqCst) {
std::thread::sleep(std::time::Duration::from_millis(1));
}
println!("out stacked {}", RESULT.load(Ordering::SeqCst));
}
println!("out fresh {}", rec(100, false));
park_one();
*have = true;
}