@@ -47,63 +47,41 @@ Here is the error we get when we compile this code:
47
47
{{#include ../listings/ch21-web-server/listing-21-22/output.txt}}
48
48
```
49
49
50
- The error tells us we can’t call ` join ` because we only have a mutable borrow
51
- of each ` worker ` and ` join ` takes ownership of its argument. To solve this
52
- issue, we need to move the thread out of the ` Worker ` instance that owns
53
- ` thread ` so ` join ` can consume the thread. We did this in Listing 17-15: if
54
- ` Worker ` holds an ` Option<thread::JoinHandle<()>> ` instead, we can call the
55
- ` take ` method on the ` Option ` to move the value out of the ` Some ` variant and
56
- leave a ` None ` variant in its place. In other words, a ` Worker ` that is running
57
- will have a ` Some ` variant in ` thread ` , and when we want to clean up a
58
- ` Worker ` , we’ll replace ` Some ` with ` None ` so the ` Worker ` doesn’t have a
59
- thread to run.
60
-
61
- So we know we want to update the definition of ` Worker ` like this:
50
+ The error tells us we can’t call ` join ` because we only have a mutable borrow of
51
+ each ` worker ` and ` join ` takes ownership of its argument. To solve this issue,
52
+ we need to move the thread out of the ` Worker ` instance that owns ` thread ` so
53
+ ` join ` can consume the thread. One way to do this is by taking the same approach
54
+ we did in Listing 18-15. If ` Worker ` held an ` Option<thread::JoinHandle<()>> ` ,
55
+ we could call the ` take ` method on the ` Option ` to move the value out of the
56
+ ` Some ` variant and leave a ` None ` variant in its place. In other words, a
57
+ ` Worker ` that is running would have a ` Some ` variant in ` thread ` , and when we
58
+ wanted to clean up a ` Worker ` , we would replace ` Some ` with ` None ` so the
59
+ ` Worker ` doesn’t have a thread to run.
60
+
61
+ However, the _ only_ time this would come up would be when dropping the ` Worker ` .
62
+ In exchange, we would have to deal with an ` Option<thread::JoinHandle<()>> `
63
+ everywhere we access ` worker.thread ` . Idiomatic Rust uses ` Option ` quite a bit,
64
+ but when you find yourself wrapping something in ` Option ` as a workaround even
65
+ though you know the item will always be present, it is a good idea to look for
66
+ alternative approaches. They can make your code cleaner and less error-prone.
67
+
68
+ In this case, there is a better alternative: the ` Vec::drain ` method. It accepts
69
+ a range parameter to specify which items to remove from the ` Vec ` , and returns
70
+ an iterator of those items. Passing the ` .. ` range syntax will remove * every*
71
+ value from the ` Vec ` .
72
+
73
+ So we need to update the ` ThreadPool ` ` drop ` implementation like this:
62
74
63
75
<Listing file-name =" src/lib.rs " >
64
76
65
77
``` rust,ignore,does_not_compile
66
- {{#rustdoc_include ../listings/ch21-web-server/no-listing-04-update-worker -definition/src/lib.rs:here}}
78
+ {{#rustdoc_include ../listings/ch21-web-server/no-listing-04-update-drop -definition/src/lib.rs:here}}
67
79
```
68
80
69
81
</Listing >
70
82
71
- Now let’s lean on the compiler to find the other places that need to change.
72
- Checking this code, we get two errors:
73
-
74
- ``` console
75
- {{#include ../listings/ch21-web-server/no-listing-04-update-worker-definition/output.txt}}
76
- ```
77
-
78
- Let’s address the second error, which points to the code at the end of
79
- ` Worker::new ` ; we need to wrap the ` thread ` value in ` Some ` when we create a
80
- new ` Worker ` . Make the following changes to fix this error:
81
-
82
- <Listing file-name =" src/lib.rs " >
83
-
84
- ``` rust,ignore,does_not_compile
85
- {{#rustdoc_include ../listings/ch21-web-server/no-listing-05-fix-worker-new/src/lib.rs:here}}
86
- ```
87
-
88
- </Listing >
89
-
90
- The first error is in our ` Drop ` implementation. We mentioned earlier that we
91
- intended to call ` take ` on the ` Option ` value to move ` thread ` out of ` worker ` .
92
- The following changes will do so:
93
-
94
- <Listing file-name =" src/lib.rs " >
95
-
96
- ``` rust,ignore,not_desired_behavior
97
- {{#rustdoc_include ../listings/ch21-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs:here}}
98
- ```
99
-
100
- </Listing >
101
-
102
- As discussed in Chapter 18, the ` take ` method on ` Option ` takes the ` Some `
103
- variant out and leaves ` None ` in its place. We’re using ` if let ` to destructure
104
- the ` Some ` and get the thread; then we call ` join ` on the thread. If a worker’s
105
- thread is already ` None ` , we know that worker has already had its thread
106
- cleaned up, so nothing happens in that case.
83
+ This resolves the compiler error and does not require any other changes to our
84
+ code.
107
85
108
86
### Signaling to the Threads to Stop Listening for Jobs
109
87
@@ -120,9 +98,9 @@ implementation and then a change in the `Worker` loop.
120
98
121
99
First, we’ll change the ` ThreadPool ` ` drop ` implementation to explicitly drop
122
100
the ` sender ` before waiting for the threads to finish. Listing 21-23 shows the
123
- changes to ` ThreadPool ` to explicitly drop ` sender ` . We use the same ` Option `
124
- and ` take ` technique as we did with the thread to be able to move ` sender ` out
125
- of ` ThreadPool ` :
101
+ changes to ` ThreadPool ` to explicitly drop ` sender ` . Unlike with the ` workers ` ,
102
+ here we * do * need to use an ` Option ` to be able to move ` sender ` out of
103
+ ` ThreadPool ` with ` Option::take ` .
126
104
127
105
<Listing number =" 21-23 " file-name =" src/lib.rs " caption =" Explicitly drop `sender` before joining the worker threads " >
128
106
0 commit comments