{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/book/pulls/comments/116567764","pull_request_review_id":38198367,"id":116567764,"diff_hunk":"@@ -0,0 +1,564 @@\n+## Graceful Shutdown and Cleanup\n+\n+The code in Listing 20-21 is responding to requests asynchronously through the\n+use of a thread pool, as we intended. We get some warnings about fields that\n+we're not using in a direct way, which are a reminder that we're not cleaning\n+anything up. When we use `CTRL-C` to halt the main thread, all the other\n+threads are stopped immediately as well, even if they're in the middle of\n+serving a request.\n+\n+We're now going to implement the `Drop` trait for `ThreadPool` to call `join`\n+on each of the threads in the pool so that the threads will finish the requests\n+they're working on. Then we'll implement a way for the `ThreadPool` to tell the\n+threads they should stop accepting new requests and shut down. To see this code\n+in action, we'll modify our server to only accept two requests before\n+gracefully shutting down its thread pool.\n+\n+Let's start with implementing `Drop` for our thread pool. When the pool is\n+dropped, we should join on all of our threads to make sure they finish their\n+work. Listing 20-22 shows a first attempt at a `Drop` implementation; this code\n+won't quite work yet:\n+\n+<span class=\"filename\">Filename: src/lib.rs</span>\n+\n+```rust,ignore\n+impl Drop for ThreadPool {\n+    fn drop(&mut self) {\n+        for worker in &mut self.workers {\n+            println!(\"Shutting down worker {}\", worker.id);\n+\n+            worker.thread.join().unwrap();\n+        }\n+    }\n+}\n+```\n+\n+<span class=\"caption\">Listing 20-22: Joining each thread when the thread pool\n+goes out of scope</span>\n+\n+We loop through each of the thread pool `workers`, using `&mut` because `self`\n+is itself a mutable reference and we also need to be able to mutate `worker`.\n+We print out a message saying that this particular worker is shutting down, and\n+then we call `join` on that worker's thread. If the call to `join` fails, we\n+`unwrap` the error to panic and go into an ungraceful shutdown.\n+\n+Here's the error we get if we compile this code:\n+\n+```text\n+error[E0507]: cannot move out of borrowed content\n+  --> src/lib.rs:65:13\n+   |\n+65 |             worker.thread.join().unwrap();\n+   |             ^^^^^^ cannot move out of borrowed content\n+```\n+\n+Because we only have a mutable borrow of each `worker`, we can't call `join`:\n+`join` takes ownership of its argument. In order to solve this, we need a way\n+to move the `thread` out of the `Worker` instance that owns `thread` so that\n+`join` can consume the thread. We saw a way to do this in Listing 17-15: if the\n+`Worker` holds an `Option<thread::JoinHandle<()>` instead, we can call the\n+`take` method on the `Option` to move the value out of the `Some` variant and\n+leave a `None` variant in its place. In other words, a `Worker` that is running\n+will have a `Some` variant in `thread`, and when we want to clean up a worker,\n+we'll replace `Some` with `None` so the worker doesn't have a thread to run.\n+\n+So we know we want to update the definition of `Worker` like this:\n+\n+<span class=\"filename\">Filename: src/lib.rs</span>\n+\n+```rust\n+# use std::thread;\n+struct Worker {\n+    id: u32,\n+    thread: Option<thread::JoinHandle<()>>,\n+}\n+```\n+\n+Now let's lean on the compiler to find the other places that need to change. We\n+get two errors:\n+\n+```text\n+error: no method named `join` found for type\n+`std::option::Option<std::thread::JoinHandle<()>>` in the current scope\n+  --> src/lib.rs:65:27\n+   |\n+65 |             worker.thread.join().unwrap();\n+   |                           ^^^^\n+\n+error[E0308]: mismatched types\n+  --> src/lib.rs:89:21\n+   |\n+89 |             thread: thread,\n+   |                     ^^^^^^ expected enum `std::option::Option`, found\n+   struct `std::thread::JoinHandle`\n+   |\n+   = note: expected type `std::option::Option<std::thread::JoinHandle<()>>`\n+              found type `std::thread::JoinHandle<_>`\n+```\n+\n+The second error is pointing to the code at the end of `Worker::new`; we need\n+to wrap the `thread` value in `Some` when we create a new `Worker`:\n+\n+<span class=\"filename\">Filename: src/lib.rs</span>\n+\n+```rust,ignore\n+impl Worker {\n+    fn new(id: usize, job_receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {\n+        // ...snip...\n+\n+        Worker {\n+            id: id,\n+            thread: Some(thread),\n+        }\n+    }\n+}\n+```\n+\n+The first error is in our `Drop` implementation, and we mentioned that we'll be\n+calling `take` on the `Option` value to move `thread` out of `worker`. Here's\n+what that looks like:\n+\n+<span class=\"filename\">Filename: src/lib.rs</span>\n+\n+```rust,ignore\n+impl Drop for ThreadPool {\n+    fn drop(&mut self) {\n+        for worker in &mut self.threads {\n+            println!(\"Shutting down worker {}\", worker.id);\n+\n+            if let Some(thread) = worker.thread.take() {\n+                thread.join().unwrap();\n+            }\n+        }\n+    }\n+}\n+```\n+\n+As we saw in Chapter 17, the `take` method on `Option` takes the `Some` variant\n+out and leaves `None` in its place. We're using `if let` to destructure the\n+`Some` and get the thread, then call `join` on the thread. If a worker's thread\n+is already `None`, then we know this worker has already had its thread cleaned\n+up so we don't do anything in that case.\n+\n+With this, our code compiles without any warnings. Bad news though, this code\n+doesn't function the way we want it to yet. The key is the logic in the\n+closures that the spawned threads of the `Worker` instances run: calling `join`\n+won't shut down the threads since they `loop` forever looking for jobs. If we\n+try to drop our `ThreadPool` with this implementation, the main thread will\n+block forever waiting for the first thread to finish.\n+\n+To fix this, we're going to modify the threads to listen for either a `Job` to\n+run or a signal that they should stop listening and exit the infinite loop. So\n+instead of `Job` instances, our channel will send one of these two enum\n+variants:\n+\n+<span class=\"filename\">Filename: src/lib.rs</span>\n+\n+```rust\n+# struct Job;\n+enum Message {\n+    NewJob(Job),\n+    Terminate,\n+}\n+```\n+\n+This `Message` enum will either be a `NewJob` variant that holds the `Job` the\n+thread should run, or it will be a `Terminate` variant that will cause the\n+thread to exit its loop and stop.\n+\n+We need to adjust the channel to use values of type `Message` rather than type\n+`Job`, as shown in Listing 20-23:\n+\n+<span class=\"filename\">Filename: src/lib.rs</span>\n+\n+```rust,ignore\n+struct ThreadPool {\n+    threads: Vec<Worker>,\n+    sender: mpsc::Sender<Message>,\n+}\n+\n+// ...snip...\n+\n+impl ThreadPool {\n+    // ...snip...\n+    pub fn new(size: usize) -> ThreadPool {\n+        assert!(size > 0);\n+\n+        let (job_sender, job_receiver) = mpsc::channel::<Message>();\n+\n+        // ...snip...\n+    }\n+\n+    pub fn execute<F>(&self, f: F)\n+        where\n+            F: FnOnce() + Send + 'static\n+    {\n+        let job = Box::new(f);\n+\n+        self.sender.send(Message::NewJob(job)).unwrap();\n+    }\n+}\n+\n+// ...snip...\n+\n+impl Worker {\n+    fn new(id: usize, job_receiver: Arc<Mutex<mpsc::Receiver<Message>>>) ->\n+        Worker {\n+        // ...snip...","path":"second-edition/src/ch20-06-graceful-shutdown-and-cleanup.md","position":207,"original_position":207,"commit_id":"713e633633b1bbe509f1375f722989c3d9037950","original_commit_id":"713e633633b1bbe509f1375f722989c3d9037950","user":{"login":"carols10cents","id":193874,"avatar_url":"https://avatars1.githubusercontent.com/u/193874?v=3","gravatar_id":"","url":"https://api.github.com/users/carols10cents","html_url":"https://github.com/carols10cents","followers_url":"https://api.github.com/users/carols10cents/followers","following_url":"https://api.github.com/users/carols10cents/following{/other_user}","gists_url":"https://api.github.com/users/carols10cents/gists{/gist_id}","starred_url":"https://api.github.com/users/carols10cents/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carols10cents/subscriptions","organizations_url":"https://api.github.com/users/carols10cents/orgs","repos_url":"https://api.github.com/users/carols10cents/repos","events_url":"https://api.github.com/users/carols10cents/events{/privacy}","received_events_url":"https://api.github.com/users/carols10cents/received_events","type":"User","site_admin":false},"body":"Yup I messed up!","created_at":"2017-05-15T18:35:00Z","updated_at":"2017-05-15T18:35:00Z","html_url":"https://github.com/rust-lang/book/pull/584#discussion_r116567764","pull_request_url":"https://api.github.com/repos/rust-lang/book/pulls/584","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/book/pulls/comments/116567764"},"html":{"href":"https://github.com/rust-lang/book/pull/584#discussion_r116567764"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/book/pulls/584"}}},"pull_request":{"url":"https://api.github.com/repos/rust-lang/book/pulls/584","id":113535273,"html_url":"https://github.com/rust-lang/book/pull/584","diff_url":"https://github.com/rust-lang/book/pull/584.diff","patch_url":"https://github.com/rust-lang/book/pull/584.patch","issue_url":"https://api.github.com/repos/rust-lang/book/issues/584","number":584,"state":"open","locked":false,"title":"Chapter 20: build a web server","user":{"login":"steveklabnik","id":27786,"avatar_url":"https://avatars1.githubusercontent.com/u/27786?v=3","gravatar_id":"","url":"https://api.github.com/users/steveklabnik","html_url":"https://github.com/steveklabnik","followers_url":"https://api.github.com/users/steveklabnik/followers","following_url":"https://api.github.com/users/steveklabnik/following{/other_user}","gists_url":"https://api.github.com/users/steveklabnik/gists{/gist_id}","starred_url":"https://api.github.com/users/steveklabnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steveklabnik/subscriptions","organizations_url":"https://api.github.com/users/steveklabnik/orgs","repos_url":"https://api.github.com/users/steveklabnik/repos","events_url":"https://api.github.com/users/steveklabnik/events{/privacy}","received_events_url":"https://api.github.com/users/steveklabnik/received_events","type":"User","site_admin":false},"body":"The first half is here; second half coming tomorrow.","created_at":"2017-03-30T22:06:38Z","updated_at":"2017-05-15T18:35:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6d864faa430bd830235a53c467e1041679ff69f5","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/rust-lang/book/pulls/584/commits","review_comments_url":"https://api.github.com/repos/rust-lang/book/pulls/584/comments","review_comment_url":"https://api.github.com/repos/rust-lang/book/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rust-lang/book/issues/584/comments","statuses_url":"https://api.github.com/repos/rust-lang/book/statuses/713e633633b1bbe509f1375f722989c3d9037950","head":{"label":"rust-lang:ch20","ref":"ch20","sha":"713e633633b1bbe509f1375f722989c3d9037950","user":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars2.githubusercontent.com/u/5430905?v=3","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"repo":{"id":47854924,"name":"book","full_name":"rust-lang/book","owner":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars2.githubusercontent.com/u/5430905?v=3","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rust-lang/book","description":"The Rust Programming Language","fork":false,"url":"https://api.github.com/repos/rust-lang/book","forks_url":"https://api.github.com/repos/rust-lang/book/forks","keys_url":"https://api.github.com/repos/rust-lang/book/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rust-lang/book/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rust-lang/book/teams","hooks_url":"https://api.github.com/repos/rust-lang/book/hooks","issue_events_url":"https://api.github.com/repos/rust-lang/book/issues/events{/number}","events_url":"https://api.github.com/repos/rust-lang/book/events","assignees_url":"https://api.github.com/repos/rust-lang/book/assignees{/user}","branches_url":"https://api.github.com/repos/rust-lang/book/branches{/branch}","tags_url":"https://api.github.com/repos/rust-lang/book/tags","blobs_url":"https://api.github.com/repos/rust-lang/book/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rust-lang/book/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rust-lang/book/git/refs{/sha}","trees_url":"https://api.github.com/repos/rust-lang/book/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rust-lang/book/statuses/{sha}","languages_url":"https://api.github.com/repos/rust-lang/book/languages","stargazers_url":"https://api.github.com/repos/rust-lang/book/stargazers","contributors_url":"https://api.github.com/repos/rust-lang/book/contributors","subscribers_url":"https://api.github.com/repos/rust-lang/book/subscribers","subscription_url":"https://api.github.com/repos/rust-lang/book/subscription","commits_url":"https://api.github.com/repos/rust-lang/book/commits{/sha}","git_commits_url":"https://api.github.com/repos/rust-lang/book/git/commits{/sha}","comments_url":"https://api.github.com/repos/rust-lang/book/comments{/number}","issue_comment_url":"https://api.github.com/repos/rust-lang/book/issues/comments{/number}","contents_url":"https://api.github.com/repos/rust-lang/book/contents/{+path}","compare_url":"https://api.github.com/repos/rust-lang/book/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rust-lang/book/merges","archive_url":"https://api.github.com/repos/rust-lang/book/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rust-lang/book/downloads","issues_url":"https://api.github.com/repos/rust-lang/book/issues{/number}","pulls_url":"https://api.github.com/repos/rust-lang/book/pulls{/number}","milestones_url":"https://api.github.com/repos/rust-lang/book/milestones{/number}","notifications_url":"https://api.github.com/repos/rust-lang/book/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rust-lang/book/labels{/name}","releases_url":"https://api.github.com/repos/rust-lang/book/releases{/id}","deployments_url":"https://api.github.com/repos/rust-lang/book/deployments","created_at":"2015-12-11T22:49:49Z","updated_at":"2017-05-15T17:07:50Z","pushed_at":"2017-05-14T14:49:44Z","git_url":"git://github.com/rust-lang/book.git","ssh_url":"git@github.com:rust-lang/book.git","clone_url":"https://github.com/rust-lang/book.git","svn_url":"https://github.com/rust-lang/book","homepage":"https://doc.rust-lang.org/nightly/book/","size":15986,"stargazers_count":845,"watchers_count":845,"language":"Rust","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":225,"mirror_url":null,"open_issues_count":93,"forks":225,"open_issues":93,"watchers":845,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"1cb74f8bad3dac8cc0622ccec1326a058f4e609c","user":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars2.githubusercontent.com/u/5430905?v=3","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"repo":{"id":47854924,"name":"book","full_name":"rust-lang/book","owner":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars2.githubusercontent.com/u/5430905?v=3","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rust-lang/book","description":"The Rust Programming Language","fork":false,"url":"https://api.github.com/repos/rust-lang/book","forks_url":"https://api.github.com/repos/rust-lang/book/forks","keys_url":"https://api.github.com/repos/rust-lang/book/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rust-lang/book/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rust-lang/book/teams","hooks_url":"https://api.github.com/repos/rust-lang/book/hooks","issue_events_url":"https://api.github.com/repos/rust-lang/book/issues/events{/number}","events_url":"https://api.github.com/repos/rust-lang/book/events","assignees_url":"https://api.github.com/repos/rust-lang/book/assignees{/user}","branches_url":"https://api.github.com/repos/rust-lang/book/branches{/branch}","tags_url":"https://api.github.com/repos/rust-lang/book/tags","blobs_url":"https://api.github.com/repos/rust-lang/book/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rust-lang/book/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rust-lang/book/git/refs{/sha}","trees_url":"https://api.github.com/repos/rust-lang/book/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rust-lang/book/statuses/{sha}","languages_url":"https://api.github.com/repos/rust-lang/book/languages","stargazers_url":"https://api.github.com/repos/rust-lang/book/stargazers","contributors_url":"https://api.github.com/repos/rust-lang/book/contributors","subscribers_url":"https://api.github.com/repos/rust-lang/book/subscribers","subscription_url":"https://api.github.com/repos/rust-lang/book/subscription","commits_url":"https://api.github.com/repos/rust-lang/book/commits{/sha}","git_commits_url":"https://api.github.com/repos/rust-lang/book/git/commits{/sha}","comments_url":"https://api.github.com/repos/rust-lang/book/comments{/number}","issue_comment_url":"https://api.github.com/repos/rust-lang/book/issues/comments{/number}","contents_url":"https://api.github.com/repos/rust-lang/book/contents/{+path}","compare_url":"https://api.github.com/repos/rust-lang/book/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rust-lang/book/merges","archive_url":"https://api.github.com/repos/rust-lang/book/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rust-lang/book/downloads","issues_url":"https://api.github.com/repos/rust-lang/book/issues{/number}","pulls_url":"https://api.github.com/repos/rust-lang/book/pulls{/number}","milestones_url":"https://api.github.com/repos/rust-lang/book/milestones{/number}","notifications_url":"https://api.github.com/repos/rust-lang/book/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rust-lang/book/labels{/name}","releases_url":"https://api.github.com/repos/rust-lang/book/releases{/id}","deployments_url":"https://api.github.com/repos/rust-lang/book/deployments","created_at":"2015-12-11T22:49:49Z","updated_at":"2017-05-15T17:07:50Z","pushed_at":"2017-05-14T14:49:44Z","git_url":"git://github.com/rust-lang/book.git","ssh_url":"git@github.com:rust-lang/book.git","clone_url":"https://github.com/rust-lang/book.git","svn_url":"https://github.com/rust-lang/book","homepage":"https://doc.rust-lang.org/nightly/book/","size":15986,"stargazers_count":845,"watchers_count":845,"language":"Rust","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":225,"mirror_url":null,"open_issues_count":93,"forks":225,"open_issues":93,"watchers":845,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/book/pulls/584"},"html":{"href":"https://github.com/rust-lang/book/pull/584"},"issue":{"href":"https://api.github.com/repos/rust-lang/book/issues/584"},"comments":{"href":"https://api.github.com/repos/rust-lang/book/issues/584/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/book/pulls/584/comments"},"review_comment":{"href":"https://api.github.com/repos/rust-lang/book/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rust-lang/book/pulls/584/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/book/statuses/713e633633b1bbe509f1375f722989c3d9037950"}}}}
{"actor":{"display_login":"carols10cents"}}