]> git.proxmox.com Git - rustc.git/blob - src/doc/book/listings/ch20-web-server/listing-20-25/src/lib.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / listings / ch20-web-server / listing-20-25 / src / lib.rs
1 use std::{
2 sync::{mpsc, Arc, Mutex},
3 thread,
4 };
5
6 pub struct ThreadPool {
7 workers: Vec<Worker>,
8 sender: Option<mpsc::Sender<Job>>,
9 }
10
11 type Job = Box<dyn FnOnce() + Send + 'static>;
12
13 impl ThreadPool {
14 /// Create a new ThreadPool.
15 ///
16 /// The size is the number of threads in the pool.
17 ///
18 /// # Panics
19 ///
20 /// The `new` function will panic if the size is zero.
21 pub fn new(size: usize) -> ThreadPool {
22 assert!(size > 0);
23
24 let (sender, receiver) = mpsc::channel();
25
26 let receiver = Arc::new(Mutex::new(receiver));
27
28 let mut workers = Vec::with_capacity(size);
29
30 for id in 0..size {
31 workers.push(Worker::new(id, Arc::clone(&receiver)));
32 }
33
34 ThreadPool {
35 workers,
36 sender: Some(sender),
37 }
38 }
39
40 pub fn execute<F>(&self, f: F)
41 where
42 F: FnOnce() + Send + 'static,
43 {
44 let job = Box::new(f);
45
46 self.sender.as_ref().unwrap().send(job).unwrap();
47 }
48 }
49
50 impl Drop for ThreadPool {
51 fn drop(&mut self) {
52 drop(self.sender.take());
53
54 for worker in &mut self.workers {
55 println!("Shutting down worker {}", worker.id);
56
57 if let Some(thread) = worker.thread.take() {
58 thread.join().unwrap();
59 }
60 }
61 }
62 }
63
64 struct Worker {
65 id: usize,
66 thread: Option<thread::JoinHandle<()>>,
67 }
68
69 impl Worker {
70 fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
71 let thread = thread::spawn(move || loop {
72 let message = receiver.lock().unwrap().recv();
73
74 match message {
75 Ok(job) => {
76 println!("Worker {id} got a job; executing.");
77
78 job();
79 }
80 Err(_) => {
81 println!("Worker {id} disconnected; shutting down.");
82 break;
83 }
84 }
85 });
86
87 Worker {
88 id,
89 thread: Some(thread),
90 }
91 }
92 }