289. JoinHandle::is_finished — Check on a Worker Without Blocking on join()
join() tells you when a thread is done — by blocking until it is. Sometimes you just want to peek: still running, or can I collect the result now?
The DIY version is an Arc<AtomicBool> that the worker sets as its last statement. It has a hole: if the thread panics before that store, the flag stays false forever and your supervisor waits on a corpse.
JoinHandle::is_finished (stable since 1.61) asks the handle directly. It returns immediately, and it reports termination — a worker that panicked counts as finished, because it is:
| |
is_finished() doesn’t consume the handle, so you can poll in a loop and still join() afterwards. And you should: is_finished() == true is exactly the guarantee that join() won’t block, and join() is where the result — or the panic — comes out:
| |
That second half matters. is_finished tells you that a thread ended, never how — a clean return and a panic look identical until you join(). Name your threads with thread::Builder and the panic message at least tells you who died.
One boundary to respect: this is a check-in tool, not a synchronization primitive. A hot while !w.is_finished() {} loop is the same spin-wait sin as the atomic-counter hack from this morning’s Barrier bite. If you need to wait for completion, join() already does that; if you need results as they arrive, use a channel. Reach for is_finished when the answer “not yet” is useful — progress bars, health checks, deciding whether to steal a straggler’s remaining work.