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