@@ -30,11 +30,10 @@ the underlying data. Instead, a `Bytes` instance is a reference-counted handle
30
30
to some underlying data. The ` Bytes ` type is roughly an ` Arc<Vec<u8>> ` but with
31
31
some added capabilities.
32
32
33
- To depend on ` bytes ` , add the following to your ` Cargo.toml ` in the
34
- ` [dependencies] ` section:
33
+ Add the ` bytes ` dependency to your ` Cargo.toml ` file:
35
34
36
- ``` toml
37
- bytes = " 1 "
35
+ ``` bash
36
+ cargo add bytes
38
37
```
39
38
40
39
[ `bytes` ] : https://docs.rs/bytes/1/bytes/struct.Bytes.html
@@ -154,6 +153,7 @@ async fn process(socket: TcpStream, db: Db) {
154
153
# Holding a ` MutexGuard ` across an ` .await `
155
154
156
155
You might write code that looks like this:
156
+
157
157
``` rust
158
158
use std :: sync :: {Mutex , MutexGuard };
159
159
@@ -165,8 +165,10 @@ async fn increment_and_do_stuff(mutex: &Mutex<i32>) {
165
165
} // lock goes out of scope here
166
166
# async fn do_something_async () {}
167
167
```
168
+
168
169
When you try to spawn something that calls this function, you will encounter the
169
170
following error message:
171
+
170
172
``` text
171
173
error: future cannot be sent between threads safely
172
174
--> src/lib.rs:13:5
@@ -191,11 +193,13 @@ note: future is not `Send` as this value is used across an await
191
193
8 | }
192
194
| - `mut lock` is later dropped here
193
195
```
196
+
194
197
This happens because the ` std::sync::MutexGuard ` type is ** not** ` Send ` . This
195
198
means that you can't send a mutex lock to another thread, and the error happens
196
199
because the Tokio runtime can move a task between threads at every ` .await ` .
197
200
To avoid this, you should restructure your code such that the mutex lock's
198
201
destructor runs before the ` .await ` .
202
+
199
203
``` rust
200
204
# use std :: sync :: {Mutex , MutexGuard };
201
205
// This works!
@@ -209,7 +213,9 @@ async fn increment_and_do_stuff(mutex: &Mutex<i32>) {
209
213
}
210
214
# async fn do_something_async () {}
211
215
```
216
+
212
217
Note that this does not work:
218
+
213
219
``` rust
214
220
use std :: sync :: {Mutex , MutexGuard };
215
221
@@ -223,6 +229,7 @@ async fn increment_and_do_stuff(mutex: &Mutex<i32>) {
223
229
}
224
230
# async fn do_something_async () {}
225
231
```
232
+
226
233
This is because the compiler currently calculates whether a future is ` Send `
227
234
based on scope information only. The compiler will hopefully be updated to
228
235
support explicitly dropping it in the future, but for now, you must explicitly
@@ -250,6 +257,7 @@ We will discuss some approaches to avoid these issues below:
250
257
251
258
The safest way to handle a mutex is to wrap it in a struct, and lock the mutex
252
259
only inside non-async methods on that struct.
260
+
253
261
``` rust
254
262
use std :: sync :: Mutex ;
255
263
@@ -270,6 +278,7 @@ async fn increment_and_do_stuff(can_incr: &CanIncrement) {
270
278
}
271
279
# async fn do_something_async () {}
272
280
```
281
+
273
282
This pattern guarantees that you won't run into the ` Send ` error, because the
274
283
mutex guard does not appear anywhere in an async function. It also protects you
275
284
from deadlocks, when using crates whose ` MutexGuard ` implements ` Send ` .
@@ -288,6 +297,7 @@ The [`tokio::sync::Mutex`] type provided by Tokio can also be used. The primary
288
297
feature of the Tokio mutex is that it can be held across an ` .await ` without any
289
298
issues. That said, an asynchronous mutex is more expensive than an ordinary
290
299
mutex, and it is typically better to use one of the two other approaches.
300
+
291
301
``` rust
292
302
use tokio :: sync :: Mutex ; // note! This uses the Tokio mutex
293
303
0 commit comments