Skip to content

Commit 41920d0

Browse files
committed
2 parents efbcaed + d1a359f commit 41920d0

File tree

6 files changed

+158
-1
lines changed

6 files changed

+158
-1
lines changed

code/ch20/c24/404.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Hello!</title>
6+
</head>
7+
<body>
8+
<h1>Oops!</h1>
9+
<p>Sorry, I don't know what you're asking for.</p>
10+
</body>
11+
</html>

code/ch20/c24/hello.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Hello!</title>
6+
</head>
7+
<body>
8+
<h1>Hello!</h1>
9+
<p>Hi from Rust</p>
10+
</body>
11+
</html>

code/ch20/c24/src/main.rs

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,116 @@
1+
use std::sync::{Arc, mpsc, Mutex};
2+
use std::fs;
3+
use std::io::prelude::*;
4+
use std::net::{TcpListener, TcpStream};
5+
use std::thread;
6+
use std::time::Duration;
7+
18
fn main() {
2-
println!("Hello, world!");
9+
10+
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
11+
let pool = ThreadPool::new(4);
12+
for stream in listener.incoming() {
13+
pool.execute(|| {
14+
handle_tcpstream(stream.unwrap());
15+
});
16+
17+
}
18+
}
19+
20+
fn handle_tcpstream(mut stream: TcpStream) {
21+
let mut buffer = [0u8; 1024 * 8];
22+
stream.read(&mut buffer).unwrap();
23+
let get = b"GET / HTTP/1.1\r\n";
24+
let sleep = b"GET /sleep HTTP/1.1\r\n";
25+
let (status_line, filename) = if buffer.starts_with(get) {
26+
("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
27+
} else if buffer.starts_with(sleep) {
28+
thread::sleep(Duration::from_secs(5));
29+
("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
30+
} else {
31+
("HTTP/1.1 404 NOT FOUND\r\n\r\n", "404.html")
32+
};
33+
let html = fs::read_to_string(filename).unwrap();
34+
let resp = format!("{}{}", status_line, html);
35+
stream.write(resp.as_bytes()).unwrap();
36+
stream.flush().unwrap();
37+
}
38+
39+
type Job = Box<dyn FnOnce() + Send + 'static>;
40+
41+
enum Message {
42+
NewJob(Job),
43+
Terminate,
44+
}
45+
struct Worker {
46+
id: usize,
47+
thread: Option<thread::JoinHandle<()>>
48+
}
49+
50+
impl Worker {
51+
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
52+
let thread = thread::spawn(move || loop {
53+
let msg = receiver.lock().unwrap().recv().unwrap();
54+
match msg {
55+
Message::NewJob(j) => {
56+
println!("Worker {} got a job; executing.", id);
57+
j()
58+
},
59+
Message::Terminate => {
60+
println!("Worker {} was told to terminate.", id);
61+
break;
62+
},
63+
}
64+
});
65+
Worker{
66+
id,
67+
thread: Some(thread),
68+
}
69+
}
70+
}
71+
72+
pub struct ThreadPool {
73+
workers: Vec<Worker>,
74+
sender: mpsc::Sender<Message>,
75+
76+
}
77+
78+
impl ThreadPool {
79+
pub fn new(size: usize) -> ThreadPool {
80+
let mut workers = Vec::with_capacity(size);
81+
let (sender, rec) = mpsc::channel();
82+
let receiver = Arc::new(Mutex::new(rec));
83+
for id in 0..size {
84+
workers.push(Worker::new(id, Arc::clone(&receiver)));
85+
}
86+
ThreadPool{
87+
workers,
88+
sender,
89+
}
90+
}
91+
92+
pub fn execute<T>(&self, t: T)
93+
where
94+
T: FnOnce() + Send + 'static,
95+
{
96+
let job = Box::new(t);
97+
self.sender.send(Message::NewJob(job)).unwrap();
98+
}
99+
}
100+
101+
impl Drop for ThreadPool {
102+
fn drop(&mut self) {
103+
println!("Sending terminate message to all workers.");
104+
for _ in &self.workers {
105+
self.sender.send(Message::Terminate).unwrap();
106+
}
107+
println!("Shutting down all workers.");
108+
109+
for worker in &mut self.workers {
110+
println!("Shutting down worker {}", worker.id);
111+
if let Some(thread) = worker.thread.take() {
112+
thread.join().unwrap();
113+
}
114+
}
115+
}
3116
}

code/ch20/c24/src/pool.rs

Whitespace-only changes.

code/ch20/c25/404.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Hello!</title>
6+
</head>
7+
<body>
8+
<h1>Oops!</h1>
9+
<p>Sorry, I don't know what you're asking for.</p>
10+
</body>
11+
</html>

code/ch20/c25/hello.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Hello!</title>
6+
</head>
7+
<body>
8+
<h1>Hello!</h1>
9+
<p>Hi from Rust</p>
10+
</body>
11+
</html>

0 commit comments

Comments
 (0)