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