Skip to content

Commit 7636658

Browse files
committed
update chapter20
1 parent 15d00e8 commit 7636658

File tree

3 files changed

+116
-11
lines changed

3 files changed

+116
-11
lines changed

20 Building a Multithreaded Web Server.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,11 @@
7474

7575
## 3.1 Implementing the Drop Trait on ThreadPool
7676

77+
The error tells us we can’t call join because we only have a mutable borrow of each worker and join takes ownership of its argument.
78+
We did this in Listing 17-15: if `Worker` holds an `Option<thread::JoinHandle<()>>` instead, we can call the `take` method on the Option to move the value out of the `Some` variant and leave a `None` variant in its place.
7779

7880

81+
## 3.2 Signaling to the Threads to Stop Listening for Jobs
7982

8083

8184

@@ -84,12 +87,14 @@
8487

8588

8689

90+
We could do more here! If you want to continue enhancing this project, here are some ideas:
8791

92+
- Add more documentation to `ThreadPool` and its public methods.
93+
- Add tests of the library’s functionality.
94+
- Change calls to `unwrap` to more robust error handling.
95+
- Use `ThreadPool` to perform some task other than serving web requests.
96+
- Find a thread pool crate on crates.io and implement a similar web server using the crate instead. Then compare its API and robustness to the thread pool we implemented.
8897

8998

90-
91-
92-
93-
94-
99+
# 4 Summary
95100

code/ch20/c22/src/main.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn main() {
99
type Job = Box<dyn FnOnce() + Send + 'static>;
1010
struct Worker {
1111
id: usize,
12-
thread: thread::JoinHandle<()>,
12+
thread: Option<thread::JoinHandle<()>>,
1313
}
1414

1515
impl Worker {
@@ -20,7 +20,9 @@ impl Worker {
2020
job()
2121
}
2222
});
23-
Worker{id, thread}
23+
Worker{id,
24+
thread:Some(thread)
25+
}
2426
}
2527
}
2628

@@ -52,9 +54,18 @@ impl Drop for ThreadPool {
5254
fn drop(&mut self) {
5355
for worker in &mut self.workers {
5456
println!("Shutting down worker {}", worker.id);
55-
worker.thread.join().unwrap();
56-
}
57-
}
58-
}
57+
// worker.thread.join().unwrap();
5958

59+
// OK
60+
if let Some(thread) = worker.thread.take() {
61+
thread.join().unwrap();
62+
}
6063

64+
// OK
65+
// match worker.thread.take() {
66+
// Some(x) => x.join().unwrap(),
67+
// None =>{},
68+
// }
69+
}
70+
}
71+
}

code/ch20/c23/src/main.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,92 @@
1+
use std::sync::{Arc, mpsc, Mutex};
2+
use std::thread;
3+
use std::time::Duration;
4+
15
fn main() {
26
println!("Hello, world!");
37
}
8+
9+
type Job = Box<dyn FnOnce() + Send + 'static>;
10+
11+
enum Message {
12+
NewJob(Job),
13+
Terminate,
14+
}
15+
16+
struct Worker{
17+
id: usize,
18+
thread: Option<thread::JoinHandle<()>>,
19+
}
20+
21+
impl Worker {
22+
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
23+
let thread = thread::spawn(move|| loop {
24+
let message = receiver.lock().unwrap().recv().unwrap();
25+
match message {
26+
Message::NewJob(job) => {
27+
println!("Worker {} got a job; executing.", id);
28+
job();
29+
},
30+
Message::Terminate => {
31+
println!("Worker {} was told to terminate.", id);
32+
break;
33+
},
34+
}
35+
});
36+
37+
Worker{
38+
id,
39+
thread: Some(thread),
40+
}
41+
}
42+
}
43+
44+
struct ThreadPool {
45+
workers: Vec<Worker>,
46+
sender: mpsc::Sender<Message>,
47+
}
48+
49+
impl ThreadPool {
50+
pub fn new(size: usize) -> ThreadPool {
51+
let (sender, receiver) = mpsc::channel();
52+
let rece = Arc::new(Mutex::new(receiver));
53+
let mut workers = Vec::with_capacity(size);
54+
55+
for id in 0..size {
56+
workers.push(Worker::new(id, Arc::clone(&rece)));
57+
}
58+
ThreadPool{
59+
workers,
60+
sender
61+
}
62+
}
63+
64+
pub fn execute<T>(&self, t: T)
65+
where
66+
T: FnOnce() + Send + 'static,
67+
{
68+
let job = Box::new(t);
69+
self.sender.send(Message::NewJob(job)).unwrap();
70+
}
71+
}
72+
73+
impl Drop for ThreadPool {
74+
75+
fn drop(&mut self) {
76+
println!("Sending terminate message to all workers.");
77+
78+
for _ in &self.workers {
79+
self.sender.send(Message::Terminate).unwrap();
80+
}
81+
82+
println!("Shutting down all workers.");
83+
84+
for w in &mut self.workers {
85+
println!("Shutting down worker {}", w.id);
86+
if let Some(thread) = w.thread.take() {
87+
thread.join().unwrap();
88+
}
89+
}
90+
91+
}
92+
}

0 commit comments

Comments
 (0)