multi_threaded/
multi_threaded.rs

1// An example that creates multiple Unit contexts, each with their own state,
2// and some global state shared through an Arc.
3
4use std::io::Write;
5use std::sync::atomic::{AtomicI32, Ordering};
6use std::sync::Arc;
7
8use unit_rs::{Request, Unit};
9
10fn main() {
11    let mut threads = Vec::new();
12
13    // Global state, available through a shared reference.
14    let global_visits = Arc::new(AtomicI32::new(0));
15
16    for thread_id in 0..4 {
17        let global_visits = global_visits.clone();
18        let handle = std::thread::spawn(move || {
19            worker(thread_id, global_visits);
20        });
21        threads.push(handle);
22    }
23
24    for handle in threads {
25        handle.join().unwrap();
26    }
27}
28
29fn worker(thread_id: i32, global_visits: Arc<AtomicI32>) {
30    let mut unit = Unit::new().unwrap();
31
32    // Thread state, available through a mutable, unique reference.
33    let mut thread_visits = 0;
34
35    unit.set_request_handler(move |req: Request| {
36        if req.path() == "/panic" {
37            // This library supports safely forwarding panics through the FFI.
38            panic!("The /panic path panics!")
39        }
40
41        let headers = &[("Content-Type", "text/plain")];
42        let body = "Hello world!\n";
43        req.send_response(200, headers, body)?;
44        thread_visits += 1;
45        global_visits.fetch_add(1, Ordering::Release);
46
47        req.send_chunk_with_buffer(4096, |buf| {
48            writeln!(
49                buf,
50                "Thread {} visits: {} (global visits: {})",
51                thread_id,
52                thread_visits,
53                global_visits.load(Ordering::Acquire),
54            )
55            .unwrap();
56            Ok(())
57        })?;
58
59        Ok(())
60    });
61
62    unit.run();
63}