rust
42 lines · 7 steps
Graceful thread shutdown with an atomic flag
A worker pool signals its threads to stop by flipping one shared atomic boolean, then joins them cleanly.
Explained by
highlit
1use std::sync::atomic::{AtomicBool, Ordering};
2use std::sync::Arc;
3use std::thread;
4use std::time::Duration;
5
6struct WorkerPool {
7 shutdown: Arc<AtomicBool>,
8 handles: Vec<thread::JoinHandle<()>>,
9}
10
11impl WorkerPool {
12 fn new(workers: usize) -> Self {
13 let shutdown = Arc::new(AtomicBool::new(false));
14 let mut handles = Vec::with_capacity(workers);
15
16 for id in 0..workers {
17 let flag = Arc::clone(&shutdown);
18 handles.push(thread::spawn(move || {
19 while !flag.load(Ordering::Acquire) {
20 process_next_task(id);
21 thread::sleep(Duration::from_millis(50));
22 }
23 eprintln!("worker {id} draining and exiting");
24 }));
25 }
26
27 WorkerPool { shutdown, handles }
28 }
29
30 fn shutdown(self) {
31 self.shutdown.store(true, Ordering::Release);
32 for handle in self.handles {
33 let _ = handle.join();
34 }
35 }
36}
37
38impl Drop for WorkerPool {
39 fn drop(&mut self) {
40 self.shutdown.store(true, Ordering::Release);
41 }
42}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A single shared AtomicBool is enough to coordinate cooperative shutdown across many threads without locks.
- 2Acquire/Release ordering pairs the writer's signal with each reader's check so the flag flip is reliably observed.
- 3Implementing Drop as a safety net ensures workers stop even when explicit shutdown is skipped.
Related explainers
rust
#[derive(Debug, PartialEq)] enum State { FieldStart, InUnquoted,
Parsing a CSV line with a state machine
state machine
parsing
enums
Intermediate
9 steps
php
<?php namespace App\Http\Middleware;
Idempotency keys in Laravel middleware
idempotency
middleware
caching
Advanced
8 steps
rust
use std::convert::TryFrom; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum HttpStatus {
Converting HTTP codes with TryFrom in Rust
enums
error-handling
trait-implementation
Intermediate
8 steps
rust
use axum::{ extract::{Request, State}, http::{HeaderValue, StatusCode}, middleware::Next,
API version headers with Axum middleware
middleware
http-headers
versioning
Intermediate
8 steps
rust
use axum::{ extract::Path, http::StatusCode, routing::{get, post},
Building a REST resource in Axum
rest-api
routing
serialization
Intermediate
9 steps
rust
use chrono::NaiveDate; use serde::{Deserialize, Deserializer}; #[derive(Debug, Deserialize)]
Custom date parsing with serde in Rust
serde
deserialization
csv-parsing
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/graceful-thread-shutdown-with-an-atomic-flag-explained-rust-0685/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.