1 | #![cfg_attr (not(feature = "sync" ), allow(unreachable_pub, dead_code))] |
2 | |
3 | use crate::sync::batch_semaphore as semaphore; |
4 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
5 | use crate::util::trace; |
6 | |
7 | use std::cell::UnsafeCell; |
8 | use std::error::Error; |
9 | use std::marker::PhantomData; |
10 | use std::ops::{Deref, DerefMut}; |
11 | use std::sync::Arc; |
12 | use std::{fmt, mem, ptr}; |
13 | |
14 | /// An asynchronous `Mutex`-like type. |
15 | /// |
16 | /// This type acts similarly to [`std::sync::Mutex`], with two major |
17 | /// differences: [`lock`] is an async method so does not block, and the lock |
18 | /// guard is designed to be held across `.await` points. |
19 | /// |
20 | /// # Which kind of mutex should you use? |
21 | /// |
22 | /// Contrary to popular belief, it is ok and often preferred to use the ordinary |
23 | /// [`Mutex`][std] from the standard library in asynchronous code. |
24 | /// |
25 | /// The feature that the async mutex offers over the blocking mutex is the |
26 | /// ability to keep it locked across an `.await` point. This makes the async |
27 | /// mutex more expensive than the blocking mutex, so the blocking mutex should |
28 | /// be preferred in the cases where it can be used. The primary use case for the |
29 | /// async mutex is to provide shared mutable access to IO resources such as a |
30 | /// database connection. If the value behind the mutex is just data, it's |
31 | /// usually appropriate to use a blocking mutex such as the one in the standard |
32 | /// library or [`parking_lot`]. |
33 | /// |
34 | /// Note that, although the compiler will not prevent the std `Mutex` from holding |
35 | /// its guard across `.await` points in situations where the task is not movable |
36 | /// between threads, this virtually never leads to correct concurrent code in |
37 | /// practice as it can easily lead to deadlocks. |
38 | /// |
39 | /// A common pattern is to wrap the `Arc<Mutex<...>>` in a struct that provides |
40 | /// non-async methods for performing operations on the data within, and only |
41 | /// lock the mutex inside these methods. The [mini-redis] example provides an |
42 | /// illustration of this pattern. |
43 | /// |
44 | /// Additionally, when you _do_ want shared access to an IO resource, it is |
45 | /// often better to spawn a task to manage the IO resource, and to use message |
46 | /// passing to communicate with that task. |
47 | /// |
48 | /// [std]: std::sync::Mutex |
49 | /// [`parking_lot`]: https://docs.rs/parking_lot |
50 | /// [mini-redis]: https://github.com/tokio-rs/mini-redis/blob/master/src/db.rs |
51 | /// |
52 | /// # Examples: |
53 | /// |
54 | /// ```rust,no_run |
55 | /// use tokio::sync::Mutex; |
56 | /// use std::sync::Arc; |
57 | /// |
58 | /// #[tokio::main] |
59 | /// async fn main() { |
60 | /// let data1 = Arc::new(Mutex::new(0)); |
61 | /// let data2 = Arc::clone(&data1); |
62 | /// |
63 | /// tokio::spawn(async move { |
64 | /// let mut lock = data2.lock().await; |
65 | /// *lock += 1; |
66 | /// }); |
67 | /// |
68 | /// let mut lock = data1.lock().await; |
69 | /// *lock += 1; |
70 | /// } |
71 | /// ``` |
72 | /// |
73 | /// |
74 | /// ```rust,no_run |
75 | /// use tokio::sync::Mutex; |
76 | /// use std::sync::Arc; |
77 | /// |
78 | /// #[tokio::main] |
79 | /// async fn main() { |
80 | /// let count = Arc::new(Mutex::new(0)); |
81 | /// |
82 | /// for i in 0..5 { |
83 | /// let my_count = Arc::clone(&count); |
84 | /// tokio::spawn(async move { |
85 | /// for j in 0..10 { |
86 | /// let mut lock = my_count.lock().await; |
87 | /// *lock += 1; |
88 | /// println!("{} {} {}" , i, j, lock); |
89 | /// } |
90 | /// }); |
91 | /// } |
92 | /// |
93 | /// loop { |
94 | /// if *count.lock().await >= 50 { |
95 | /// break; |
96 | /// } |
97 | /// } |
98 | /// println!("Count hit 50." ); |
99 | /// } |
100 | /// ``` |
101 | /// There are a few things of note here to pay attention to in this example. |
102 | /// 1. The mutex is wrapped in an [`Arc`] to allow it to be shared across |
103 | /// threads. |
104 | /// 2. Each spawned task obtains a lock and releases it on every iteration. |
105 | /// 3. Mutation of the data protected by the Mutex is done by de-referencing |
106 | /// the obtained lock as seen on lines 13 and 20. |
107 | /// |
108 | /// Tokio's Mutex works in a simple FIFO (first in, first out) style where all |
109 | /// calls to [`lock`] complete in the order they were performed. In that way the |
110 | /// Mutex is "fair" and predictable in how it distributes the locks to inner |
111 | /// data. Locks are released and reacquired after every iteration, so basically, |
112 | /// each thread goes to the back of the line after it increments the value once. |
113 | /// Note that there's some unpredictability to the timing between when the |
114 | /// threads are started, but once they are going they alternate predictably. |
115 | /// Finally, since there is only a single valid lock at any given time, there is |
116 | /// no possibility of a race condition when mutating the inner value. |
117 | /// |
118 | /// Note that in contrast to [`std::sync::Mutex`], this implementation does not |
119 | /// poison the mutex when a thread holding the [`MutexGuard`] panics. In such a |
120 | /// case, the mutex will be unlocked. If the panic is caught, this might leave |
121 | /// the data protected by the mutex in an inconsistent state. |
122 | /// |
123 | /// [`Mutex`]: struct@Mutex |
124 | /// [`MutexGuard`]: struct@MutexGuard |
125 | /// [`Arc`]: struct@std::sync::Arc |
126 | /// [`std::sync::Mutex`]: struct@std::sync::Mutex |
127 | /// [`Send`]: trait@std::marker::Send |
128 | /// [`lock`]: method@Mutex::lock |
129 | pub struct Mutex<T: ?Sized> { |
130 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
131 | resource_span: tracing::Span, |
132 | s: semaphore::Semaphore, |
133 | c: UnsafeCell<T>, |
134 | } |
135 | |
136 | /// A handle to a held `Mutex`. The guard can be held across any `.await` point |
137 | /// as it is [`Send`]. |
138 | /// |
139 | /// As long as you have this guard, you have exclusive access to the underlying |
140 | /// `T`. The guard internally borrows the `Mutex`, so the mutex will not be |
141 | /// dropped while a guard exists. |
142 | /// |
143 | /// The lock is automatically released whenever the guard is dropped, at which |
144 | /// point `lock` will succeed yet again. |
145 | #[clippy::has_significant_drop] |
146 | #[must_use = "if unused the Mutex will immediately unlock" ] |
147 | pub struct MutexGuard<'a, T: ?Sized> { |
148 | // When changing the fields in this struct, make sure to update the |
149 | // `skip_drop` method. |
150 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
151 | resource_span: tracing::Span, |
152 | lock: &'a Mutex<T>, |
153 | } |
154 | |
155 | /// An owned handle to a held `Mutex`. |
156 | /// |
157 | /// This guard is only available from a `Mutex` that is wrapped in an [`Arc`]. It |
158 | /// is identical to `MutexGuard`, except that rather than borrowing the `Mutex`, |
159 | /// it clones the `Arc`, incrementing the reference count. This means that |
160 | /// unlike `MutexGuard`, it will have the `'static` lifetime. |
161 | /// |
162 | /// As long as you have this guard, you have exclusive access to the underlying |
163 | /// `T`. The guard internally keeps a reference-counted pointer to the original |
164 | /// `Mutex`, so even if the lock goes away, the guard remains valid. |
165 | /// |
166 | /// The lock is automatically released whenever the guard is dropped, at which |
167 | /// point `lock` will succeed yet again. |
168 | /// |
169 | /// [`Arc`]: std::sync::Arc |
170 | #[clippy::has_significant_drop] |
171 | pub struct OwnedMutexGuard<T: ?Sized> { |
172 | // When changing the fields in this struct, make sure to update the |
173 | // `skip_drop` method. |
174 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
175 | resource_span: tracing::Span, |
176 | lock: Arc<Mutex<T>>, |
177 | } |
178 | |
179 | /// A handle to a held `Mutex` that has had a function applied to it via [`MutexGuard::map`]. |
180 | /// |
181 | /// This can be used to hold a subfield of the protected data. |
182 | /// |
183 | /// [`MutexGuard::map`]: method@MutexGuard::map |
184 | #[clippy::has_significant_drop] |
185 | #[must_use = "if unused the Mutex will immediately unlock" ] |
186 | pub struct MappedMutexGuard<'a, T: ?Sized> { |
187 | // When changing the fields in this struct, make sure to update the |
188 | // `skip_drop` method. |
189 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
190 | resource_span: tracing::Span, |
191 | s: &'a semaphore::Semaphore, |
192 | data: *mut T, |
193 | // Needed to tell the borrow checker that we are holding a `&mut T` |
194 | marker: PhantomData<&'a mut T>, |
195 | } |
196 | |
197 | /// A owned handle to a held `Mutex` that has had a function applied to it via |
198 | /// [`OwnedMutexGuard::map`]. |
199 | /// |
200 | /// This can be used to hold a subfield of the protected data. |
201 | /// |
202 | /// [`OwnedMutexGuard::map`]: method@OwnedMutexGuard::map |
203 | #[clippy::has_significant_drop] |
204 | #[must_use = "if unused the Mutex will immediately unlock" ] |
205 | pub struct OwnedMappedMutexGuard<T: ?Sized, U: ?Sized = T> { |
206 | // When changing the fields in this struct, make sure to update the |
207 | // `skip_drop` method. |
208 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
209 | resource_span: tracing::Span, |
210 | data: *mut U, |
211 | lock: Arc<Mutex<T>>, |
212 | } |
213 | |
214 | /// A helper type used when taking apart a `MutexGuard` without running its |
215 | /// Drop implementation. |
216 | #[allow (dead_code)] // Unused fields are still used in Drop. |
217 | struct MutexGuardInner<'a, T: ?Sized> { |
218 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
219 | resource_span: tracing::Span, |
220 | lock: &'a Mutex<T>, |
221 | } |
222 | |
223 | /// A helper type used when taking apart a `OwnedMutexGuard` without running |
224 | /// its Drop implementation. |
225 | struct OwnedMutexGuardInner<T: ?Sized> { |
226 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
227 | resource_span: tracing::Span, |
228 | lock: Arc<Mutex<T>>, |
229 | } |
230 | |
231 | /// A helper type used when taking apart a `MappedMutexGuard` without running |
232 | /// its Drop implementation. |
233 | #[allow (dead_code)] // Unused fields are still used in Drop. |
234 | struct MappedMutexGuardInner<'a, T: ?Sized> { |
235 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
236 | resource_span: tracing::Span, |
237 | s: &'a semaphore::Semaphore, |
238 | data: *mut T, |
239 | } |
240 | |
241 | /// A helper type used when taking apart a `OwnedMappedMutexGuard` without running |
242 | /// its Drop implementation. |
243 | #[allow (dead_code)] // Unused fields are still used in Drop. |
244 | struct OwnedMappedMutexGuardInner<T: ?Sized, U: ?Sized> { |
245 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
246 | resource_span: tracing::Span, |
247 | data: *mut U, |
248 | lock: Arc<Mutex<T>>, |
249 | } |
250 | |
251 | // As long as T: Send, it's fine to send and share Mutex<T> between threads. |
252 | // If T was not Send, sending and sharing a Mutex<T> would be bad, since you can |
253 | // access T through Mutex<T>. |
254 | unsafe impl<T> Send for Mutex<T> where T: ?Sized + Send {} |
255 | unsafe impl<T> Sync for Mutex<T> where T: ?Sized + Send {} |
256 | unsafe impl<T> Sync for MutexGuard<'_, T> where T: ?Sized + Send + Sync {} |
257 | unsafe impl<T> Sync for OwnedMutexGuard<T> where T: ?Sized + Send + Sync {} |
258 | unsafe impl<'a, T> Sync for MappedMutexGuard<'a, T> where T: ?Sized + Sync + 'a {} |
259 | unsafe impl<'a, T> Send for MappedMutexGuard<'a, T> where T: ?Sized + Send + 'a {} |
260 | |
261 | unsafe impl<T, U> Sync for OwnedMappedMutexGuard<T, U> |
262 | where |
263 | T: ?Sized + Send + Sync, |
264 | U: ?Sized + Send + Sync, |
265 | { |
266 | } |
267 | unsafe impl<T, U> Send for OwnedMappedMutexGuard<T, U> |
268 | where |
269 | T: ?Sized + Send, |
270 | U: ?Sized + Send, |
271 | { |
272 | } |
273 | |
274 | /// Error returned from the [`Mutex::try_lock`], [`RwLock::try_read`] and |
275 | /// [`RwLock::try_write`] functions. |
276 | /// |
277 | /// `Mutex::try_lock` operation will only fail if the mutex is already locked. |
278 | /// |
279 | /// `RwLock::try_read` operation will only fail if the lock is currently held |
280 | /// by an exclusive writer. |
281 | /// |
282 | /// `RwLock::try_write` operation will only fail if the lock is currently held |
283 | /// by any reader or by an exclusive writer. |
284 | /// |
285 | /// [`Mutex::try_lock`]: Mutex::try_lock |
286 | /// [`RwLock::try_read`]: fn@super::RwLock::try_read |
287 | /// [`RwLock::try_write`]: fn@super::RwLock::try_write |
288 | #[derive(Debug)] |
289 | pub struct TryLockError(pub(super) ()); |
290 | |
291 | impl fmt::Display for TryLockError { |
292 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
293 | write!(fmt, "operation would block" ) |
294 | } |
295 | } |
296 | |
297 | impl Error for TryLockError {} |
298 | |
299 | #[test] |
300 | #[cfg (not(loom))] |
301 | fn bounds() { |
302 | fn check_send<T: Send>() {} |
303 | fn check_unpin<T: Unpin>() {} |
304 | // This has to take a value, since the async fn's return type is unnameable. |
305 | fn check_send_sync_val<T: Send + Sync>(_t: T) {} |
306 | fn check_send_sync<T: Send + Sync>() {} |
307 | fn check_static<T: 'static>() {} |
308 | fn check_static_val<T: 'static>(_t: T) {} |
309 | |
310 | check_send::<MutexGuard<'_, u32>>(); |
311 | check_send::<OwnedMutexGuard<u32>>(); |
312 | check_unpin::<Mutex<u32>>(); |
313 | check_send_sync::<Mutex<u32>>(); |
314 | check_static::<OwnedMutexGuard<u32>>(); |
315 | |
316 | let mutex = Mutex::new(1); |
317 | check_send_sync_val(mutex.lock()); |
318 | let arc_mutex = Arc::new(Mutex::new(1)); |
319 | check_send_sync_val(arc_mutex.clone().lock_owned()); |
320 | check_static_val(arc_mutex.lock_owned()); |
321 | } |
322 | |
323 | impl<T: ?Sized> Mutex<T> { |
324 | /// Creates a new lock in an unlocked state ready for use. |
325 | /// |
326 | /// # Examples |
327 | /// |
328 | /// ``` |
329 | /// use tokio::sync::Mutex; |
330 | /// |
331 | /// let lock = Mutex::new(5); |
332 | /// ``` |
333 | #[track_caller ] |
334 | pub fn new(t: T) -> Self |
335 | where |
336 | T: Sized, |
337 | { |
338 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
339 | let resource_span = { |
340 | let location = std::panic::Location::caller(); |
341 | |
342 | tracing::trace_span!( |
343 | parent: None, |
344 | "runtime.resource" , |
345 | concrete_type = "Mutex" , |
346 | kind = "Sync" , |
347 | loc.file = location.file(), |
348 | loc.line = location.line(), |
349 | loc.col = location.column(), |
350 | ) |
351 | }; |
352 | |
353 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
354 | let s = resource_span.in_scope(|| { |
355 | tracing::trace!( |
356 | target: "runtime::resource::state_update" , |
357 | locked = false, |
358 | ); |
359 | semaphore::Semaphore::new(1) |
360 | }); |
361 | |
362 | #[cfg (any(not(tokio_unstable), not(feature = "tracing" )))] |
363 | let s = semaphore::Semaphore::new(1); |
364 | |
365 | Self { |
366 | c: UnsafeCell::new(t), |
367 | s, |
368 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
369 | resource_span, |
370 | } |
371 | } |
372 | |
373 | /// Creates a new lock in an unlocked state ready for use. |
374 | /// |
375 | /// When using the `tracing` [unstable feature], a `Mutex` created with |
376 | /// `const_new` will not be instrumented. As such, it will not be visible |
377 | /// in [`tokio-console`]. Instead, [`Mutex::new`] should be used to create |
378 | /// an instrumented object if that is needed. |
379 | /// |
380 | /// # Examples |
381 | /// |
382 | /// ``` |
383 | /// use tokio::sync::Mutex; |
384 | /// |
385 | /// static LOCK: Mutex<i32> = Mutex::const_new(5); |
386 | /// ``` |
387 | /// |
388 | /// [`tokio-console`]: https://github.com/tokio-rs/console |
389 | /// [unstable feature]: crate#unstable-features |
390 | #[cfg (not(all(loom, test)))] |
391 | pub const fn const_new(t: T) -> Self |
392 | where |
393 | T: Sized, |
394 | { |
395 | Self { |
396 | c: UnsafeCell::new(t), |
397 | s: semaphore::Semaphore::const_new(1), |
398 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
399 | resource_span: tracing::Span::none(), |
400 | } |
401 | } |
402 | |
403 | /// Locks this mutex, causing the current task to yield until the lock has |
404 | /// been acquired. When the lock has been acquired, function returns a |
405 | /// [`MutexGuard`]. |
406 | /// |
407 | /// If the mutex is available to be acquired immediately, then this call |
408 | /// will typically not yield to the runtime. However, this is not guaranteed |
409 | /// under all circumstances. |
410 | /// |
411 | /// # Cancel safety |
412 | /// |
413 | /// This method uses a queue to fairly distribute locks in the order they |
414 | /// were requested. Cancelling a call to `lock` makes you lose your place in |
415 | /// the queue. |
416 | /// |
417 | /// # Examples |
418 | /// |
419 | /// ``` |
420 | /// use tokio::sync::Mutex; |
421 | /// |
422 | /// #[tokio::main] |
423 | /// async fn main() { |
424 | /// let mutex = Mutex::new(1); |
425 | /// |
426 | /// let mut n = mutex.lock().await; |
427 | /// *n = 2; |
428 | /// } |
429 | /// ``` |
430 | pub async fn lock(&self) -> MutexGuard<'_, T> { |
431 | let acquire_fut = async { |
432 | self.acquire().await; |
433 | |
434 | MutexGuard { |
435 | lock: self, |
436 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
437 | resource_span: self.resource_span.clone(), |
438 | } |
439 | }; |
440 | |
441 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
442 | let acquire_fut = trace::async_op( |
443 | move || acquire_fut, |
444 | self.resource_span.clone(), |
445 | "Mutex::lock" , |
446 | "poll" , |
447 | false, |
448 | ); |
449 | |
450 | #[allow (clippy::let_and_return)] // this lint triggers when disabling tracing |
451 | let guard = acquire_fut.await; |
452 | |
453 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
454 | self.resource_span.in_scope(|| { |
455 | tracing::trace!( |
456 | target: "runtime::resource::state_update" , |
457 | locked = true, |
458 | ); |
459 | }); |
460 | |
461 | guard |
462 | } |
463 | |
464 | /// Blockingly locks this `Mutex`. When the lock has been acquired, function returns a |
465 | /// [`MutexGuard`]. |
466 | /// |
467 | /// This method is intended for use cases where you |
468 | /// need to use this mutex in asynchronous code as well as in synchronous code. |
469 | /// |
470 | /// # Panics |
471 | /// |
472 | /// This function panics if called within an asynchronous execution context. |
473 | /// |
474 | /// - If you find yourself in an asynchronous execution context and needing |
475 | /// to call some (synchronous) function which performs one of these |
476 | /// `blocking_` operations, then consider wrapping that call inside |
477 | /// [`spawn_blocking()`][crate::runtime::Handle::spawn_blocking] |
478 | /// (or [`block_in_place()`][crate::task::block_in_place]). |
479 | /// |
480 | /// # Examples |
481 | /// |
482 | /// ``` |
483 | /// use std::sync::Arc; |
484 | /// use tokio::sync::Mutex; |
485 | /// |
486 | /// #[tokio::main] |
487 | /// async fn main() { |
488 | /// let mutex = Arc::new(Mutex::new(1)); |
489 | /// let lock = mutex.lock().await; |
490 | /// |
491 | /// let mutex1 = Arc::clone(&mutex); |
492 | /// let blocking_task = tokio::task::spawn_blocking(move || { |
493 | /// // This shall block until the `lock` is released. |
494 | /// let mut n = mutex1.blocking_lock(); |
495 | /// *n = 2; |
496 | /// }); |
497 | /// |
498 | /// assert_eq!(*lock, 1); |
499 | /// // Release the lock. |
500 | /// drop(lock); |
501 | /// |
502 | /// // Await the completion of the blocking task. |
503 | /// blocking_task.await.unwrap(); |
504 | /// |
505 | /// // Assert uncontended. |
506 | /// let n = mutex.try_lock().unwrap(); |
507 | /// assert_eq!(*n, 2); |
508 | /// } |
509 | /// |
510 | /// ``` |
511 | #[track_caller ] |
512 | #[cfg (feature = "sync" )] |
513 | #[cfg_attr (docsrs, doc(alias = "lock_blocking" ))] |
514 | pub fn blocking_lock(&self) -> MutexGuard<'_, T> { |
515 | crate::future::block_on(self.lock()) |
516 | } |
517 | |
518 | /// Blockingly locks this `Mutex`. When the lock has been acquired, function returns an |
519 | /// [`OwnedMutexGuard`]. |
520 | /// |
521 | /// This method is identical to [`Mutex::blocking_lock`], except that the returned |
522 | /// guard references the `Mutex` with an [`Arc`] rather than by borrowing |
523 | /// it. Therefore, the `Mutex` must be wrapped in an `Arc` to call this |
524 | /// method, and the guard will live for the `'static` lifetime, as it keeps |
525 | /// the `Mutex` alive by holding an `Arc`. |
526 | /// |
527 | /// # Panics |
528 | /// |
529 | /// This function panics if called within an asynchronous execution context. |
530 | /// |
531 | /// - If you find yourself in an asynchronous execution context and needing |
532 | /// to call some (synchronous) function which performs one of these |
533 | /// `blocking_` operations, then consider wrapping that call inside |
534 | /// [`spawn_blocking()`][crate::runtime::Handle::spawn_blocking] |
535 | /// (or [`block_in_place()`][crate::task::block_in_place]). |
536 | /// |
537 | /// # Examples |
538 | /// |
539 | /// ``` |
540 | /// use std::sync::Arc; |
541 | /// use tokio::sync::Mutex; |
542 | /// |
543 | /// #[tokio::main] |
544 | /// async fn main() { |
545 | /// let mutex = Arc::new(Mutex::new(1)); |
546 | /// let lock = mutex.lock().await; |
547 | /// |
548 | /// let mutex1 = Arc::clone(&mutex); |
549 | /// let blocking_task = tokio::task::spawn_blocking(move || { |
550 | /// // This shall block until the `lock` is released. |
551 | /// let mut n = mutex1.blocking_lock_owned(); |
552 | /// *n = 2; |
553 | /// }); |
554 | /// |
555 | /// assert_eq!(*lock, 1); |
556 | /// // Release the lock. |
557 | /// drop(lock); |
558 | /// |
559 | /// // Await the completion of the blocking task. |
560 | /// blocking_task.await.unwrap(); |
561 | /// |
562 | /// // Assert uncontended. |
563 | /// let n = mutex.try_lock().unwrap(); |
564 | /// assert_eq!(*n, 2); |
565 | /// } |
566 | /// |
567 | /// ``` |
568 | #[track_caller ] |
569 | #[cfg (feature = "sync" )] |
570 | pub fn blocking_lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T> { |
571 | crate::future::block_on(self.lock_owned()) |
572 | } |
573 | |
574 | /// Locks this mutex, causing the current task to yield until the lock has |
575 | /// been acquired. When the lock has been acquired, this returns an |
576 | /// [`OwnedMutexGuard`]. |
577 | /// |
578 | /// If the mutex is available to be acquired immediately, then this call |
579 | /// will typically not yield to the runtime. However, this is not guaranteed |
580 | /// under all circumstances. |
581 | /// |
582 | /// This method is identical to [`Mutex::lock`], except that the returned |
583 | /// guard references the `Mutex` with an [`Arc`] rather than by borrowing |
584 | /// it. Therefore, the `Mutex` must be wrapped in an `Arc` to call this |
585 | /// method, and the guard will live for the `'static` lifetime, as it keeps |
586 | /// the `Mutex` alive by holding an `Arc`. |
587 | /// |
588 | /// # Cancel safety |
589 | /// |
590 | /// This method uses a queue to fairly distribute locks in the order they |
591 | /// were requested. Cancelling a call to `lock_owned` makes you lose your |
592 | /// place in the queue. |
593 | /// |
594 | /// # Examples |
595 | /// |
596 | /// ``` |
597 | /// use tokio::sync::Mutex; |
598 | /// use std::sync::Arc; |
599 | /// |
600 | /// #[tokio::main] |
601 | /// async fn main() { |
602 | /// let mutex = Arc::new(Mutex::new(1)); |
603 | /// |
604 | /// let mut n = mutex.clone().lock_owned().await; |
605 | /// *n = 2; |
606 | /// } |
607 | /// ``` |
608 | /// |
609 | /// [`Arc`]: std::sync::Arc |
610 | pub async fn lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T> { |
611 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
612 | let resource_span = self.resource_span.clone(); |
613 | |
614 | let acquire_fut = async { |
615 | self.acquire().await; |
616 | |
617 | OwnedMutexGuard { |
618 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
619 | resource_span: self.resource_span.clone(), |
620 | lock: self, |
621 | } |
622 | }; |
623 | |
624 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
625 | let acquire_fut = trace::async_op( |
626 | move || acquire_fut, |
627 | resource_span, |
628 | "Mutex::lock_owned" , |
629 | "poll" , |
630 | false, |
631 | ); |
632 | |
633 | #[allow (clippy::let_and_return)] // this lint triggers when disabling tracing |
634 | let guard = acquire_fut.await; |
635 | |
636 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
637 | guard.resource_span.in_scope(|| { |
638 | tracing::trace!( |
639 | target: "runtime::resource::state_update" , |
640 | locked = true, |
641 | ); |
642 | }); |
643 | |
644 | guard |
645 | } |
646 | |
647 | async fn acquire(&self) { |
648 | crate::trace::async_trace_leaf().await; |
649 | |
650 | self.s.acquire(1).await.unwrap_or_else(|_| { |
651 | // The semaphore was closed. but, we never explicitly close it, and |
652 | // we own it exclusively, which means that this can never happen. |
653 | unreachable!() |
654 | }); |
655 | } |
656 | |
657 | /// Attempts to acquire the lock, and returns [`TryLockError`] if the |
658 | /// lock is currently held somewhere else. |
659 | /// |
660 | /// [`TryLockError`]: TryLockError |
661 | /// # Examples |
662 | /// |
663 | /// ``` |
664 | /// use tokio::sync::Mutex; |
665 | /// # async fn dox() -> Result<(), tokio::sync::TryLockError> { |
666 | /// |
667 | /// let mutex = Mutex::new(1); |
668 | /// |
669 | /// let n = mutex.try_lock()?; |
670 | /// assert_eq!(*n, 1); |
671 | /// # Ok(()) |
672 | /// # } |
673 | /// ``` |
674 | pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError> { |
675 | match self.s.try_acquire(1) { |
676 | Ok(()) => { |
677 | let guard = MutexGuard { |
678 | lock: self, |
679 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
680 | resource_span: self.resource_span.clone(), |
681 | }; |
682 | |
683 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
684 | self.resource_span.in_scope(|| { |
685 | tracing::trace!( |
686 | target: "runtime::resource::state_update" , |
687 | locked = true, |
688 | ); |
689 | }); |
690 | |
691 | Ok(guard) |
692 | } |
693 | Err(_) => Err(TryLockError(())), |
694 | } |
695 | } |
696 | |
697 | /// Returns a mutable reference to the underlying data. |
698 | /// |
699 | /// Since this call borrows the `Mutex` mutably, no actual locking needs to |
700 | /// take place -- the mutable borrow statically guarantees no locks exist. |
701 | /// |
702 | /// # Examples |
703 | /// |
704 | /// ``` |
705 | /// use tokio::sync::Mutex; |
706 | /// |
707 | /// fn main() { |
708 | /// let mut mutex = Mutex::new(1); |
709 | /// |
710 | /// let n = mutex.get_mut(); |
711 | /// *n = 2; |
712 | /// } |
713 | /// ``` |
714 | pub fn get_mut(&mut self) -> &mut T { |
715 | unsafe { |
716 | // Safety: This is https://github.com/rust-lang/rust/pull/76936 |
717 | &mut *self.c.get() |
718 | } |
719 | } |
720 | |
721 | /// Attempts to acquire the lock, and returns [`TryLockError`] if the lock |
722 | /// is currently held somewhere else. |
723 | /// |
724 | /// This method is identical to [`Mutex::try_lock`], except that the |
725 | /// returned guard references the `Mutex` with an [`Arc`] rather than by |
726 | /// borrowing it. Therefore, the `Mutex` must be wrapped in an `Arc` to call |
727 | /// this method, and the guard will live for the `'static` lifetime, as it |
728 | /// keeps the `Mutex` alive by holding an `Arc`. |
729 | /// |
730 | /// [`TryLockError`]: TryLockError |
731 | /// [`Arc`]: std::sync::Arc |
732 | /// # Examples |
733 | /// |
734 | /// ``` |
735 | /// use tokio::sync::Mutex; |
736 | /// use std::sync::Arc; |
737 | /// # async fn dox() -> Result<(), tokio::sync::TryLockError> { |
738 | /// |
739 | /// let mutex = Arc::new(Mutex::new(1)); |
740 | /// |
741 | /// let n = mutex.clone().try_lock_owned()?; |
742 | /// assert_eq!(*n, 1); |
743 | /// # Ok(()) |
744 | /// # } |
745 | pub fn try_lock_owned(self: Arc<Self>) -> Result<OwnedMutexGuard<T>, TryLockError> { |
746 | match self.s.try_acquire(1) { |
747 | Ok(()) => { |
748 | let guard = OwnedMutexGuard { |
749 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
750 | resource_span: self.resource_span.clone(), |
751 | lock: self, |
752 | }; |
753 | |
754 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
755 | guard.resource_span.in_scope(|| { |
756 | tracing::trace!( |
757 | target: "runtime::resource::state_update" , |
758 | locked = true, |
759 | ); |
760 | }); |
761 | |
762 | Ok(guard) |
763 | } |
764 | Err(_) => Err(TryLockError(())), |
765 | } |
766 | } |
767 | |
768 | /// Consumes the mutex, returning the underlying data. |
769 | /// # Examples |
770 | /// |
771 | /// ``` |
772 | /// use tokio::sync::Mutex; |
773 | /// |
774 | /// #[tokio::main] |
775 | /// async fn main() { |
776 | /// let mutex = Mutex::new(1); |
777 | /// |
778 | /// let n = mutex.into_inner(); |
779 | /// assert_eq!(n, 1); |
780 | /// } |
781 | /// ``` |
782 | pub fn into_inner(self) -> T |
783 | where |
784 | T: Sized, |
785 | { |
786 | self.c.into_inner() |
787 | } |
788 | } |
789 | |
790 | impl<T> From<T> for Mutex<T> { |
791 | fn from(s: T) -> Self { |
792 | Self::new(s) |
793 | } |
794 | } |
795 | |
796 | impl<T> Default for Mutex<T> |
797 | where |
798 | T: Default, |
799 | { |
800 | fn default() -> Self { |
801 | Self::new(T::default()) |
802 | } |
803 | } |
804 | |
805 | impl<T: ?Sized> std::fmt::Debug for Mutex<T> |
806 | where |
807 | T: std::fmt::Debug, |
808 | { |
809 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
810 | let mut d = f.debug_struct("Mutex" ); |
811 | match self.try_lock() { |
812 | Ok(inner) => d.field("data" , &&*inner), |
813 | Err(_) => d.field("data" , &format_args!("<locked>" )), |
814 | }; |
815 | d.finish() |
816 | } |
817 | } |
818 | |
819 | // === impl MutexGuard === |
820 | |
821 | impl<'a, T: ?Sized> MutexGuard<'a, T> { |
822 | fn skip_drop(self) -> MutexGuardInner<'a, T> { |
823 | let me = mem::ManuallyDrop::new(self); |
824 | // SAFETY: This duplicates the `resource_span` and then forgets the |
825 | // original. In the end, we have not duplicated or forgotten any values. |
826 | MutexGuardInner { |
827 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
828 | resource_span: unsafe { std::ptr::read(&me.resource_span) }, |
829 | lock: me.lock, |
830 | } |
831 | } |
832 | |
833 | /// Makes a new [`MappedMutexGuard`] for a component of the locked data. |
834 | /// |
835 | /// This operation cannot fail as the [`MutexGuard`] passed in already locked the mutex. |
836 | /// |
837 | /// This is an associated function that needs to be used as `MutexGuard::map(...)`. A method |
838 | /// would interfere with methods of the same name on the contents of the locked data. |
839 | /// |
840 | /// # Examples |
841 | /// |
842 | /// ``` |
843 | /// use tokio::sync::{Mutex, MutexGuard}; |
844 | /// |
845 | /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
846 | /// struct Foo(u32); |
847 | /// |
848 | /// # #[tokio::main] |
849 | /// # async fn main() { |
850 | /// let foo = Mutex::new(Foo(1)); |
851 | /// |
852 | /// { |
853 | /// let mut mapped = MutexGuard::map(foo.lock().await, |f| &mut f.0); |
854 | /// *mapped = 2; |
855 | /// } |
856 | /// |
857 | /// assert_eq!(Foo(2), *foo.lock().await); |
858 | /// # } |
859 | /// ``` |
860 | /// |
861 | /// [`MutexGuard`]: struct@MutexGuard |
862 | /// [`MappedMutexGuard`]: struct@MappedMutexGuard |
863 | #[inline ] |
864 | pub fn map<U, F>(mut this: Self, f: F) -> MappedMutexGuard<'a, U> |
865 | where |
866 | U: ?Sized, |
867 | F: FnOnce(&mut T) -> &mut U, |
868 | { |
869 | let data = f(&mut *this) as *mut U; |
870 | let inner = this.skip_drop(); |
871 | MappedMutexGuard { |
872 | s: &inner.lock.s, |
873 | data, |
874 | marker: PhantomData, |
875 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
876 | resource_span: inner.resource_span, |
877 | } |
878 | } |
879 | |
880 | /// Attempts to make a new [`MappedMutexGuard`] for a component of the locked data. The |
881 | /// original guard is returned if the closure returns `None`. |
882 | /// |
883 | /// This operation cannot fail as the [`MutexGuard`] passed in already locked the mutex. |
884 | /// |
885 | /// This is an associated function that needs to be used as `MutexGuard::try_map(...)`. A |
886 | /// method would interfere with methods of the same name on the contents of the locked data. |
887 | /// |
888 | /// # Examples |
889 | /// |
890 | /// ``` |
891 | /// use tokio::sync::{Mutex, MutexGuard}; |
892 | /// |
893 | /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
894 | /// struct Foo(u32); |
895 | /// |
896 | /// # #[tokio::main] |
897 | /// # async fn main() { |
898 | /// let foo = Mutex::new(Foo(1)); |
899 | /// |
900 | /// { |
901 | /// let mut mapped = MutexGuard::try_map(foo.lock().await, |f| Some(&mut f.0)) |
902 | /// .expect("should not fail" ); |
903 | /// *mapped = 2; |
904 | /// } |
905 | /// |
906 | /// assert_eq!(Foo(2), *foo.lock().await); |
907 | /// # } |
908 | /// ``` |
909 | /// |
910 | /// [`MutexGuard`]: struct@MutexGuard |
911 | /// [`MappedMutexGuard`]: struct@MappedMutexGuard |
912 | #[inline ] |
913 | pub fn try_map<U, F>(mut this: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self> |
914 | where |
915 | U: ?Sized, |
916 | F: FnOnce(&mut T) -> Option<&mut U>, |
917 | { |
918 | let data = match f(&mut *this) { |
919 | Some(data) => data as *mut U, |
920 | None => return Err(this), |
921 | }; |
922 | let inner = this.skip_drop(); |
923 | Ok(MappedMutexGuard { |
924 | s: &inner.lock.s, |
925 | data, |
926 | marker: PhantomData, |
927 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
928 | resource_span: inner.resource_span, |
929 | }) |
930 | } |
931 | |
932 | /// Returns a reference to the original `Mutex`. |
933 | /// |
934 | /// ``` |
935 | /// use tokio::sync::{Mutex, MutexGuard}; |
936 | /// |
937 | /// async fn unlock_and_relock<'l>(guard: MutexGuard<'l, u32>) -> MutexGuard<'l, u32> { |
938 | /// println!("1. contains: {:?}" , *guard); |
939 | /// let mutex = MutexGuard::mutex(&guard); |
940 | /// drop(guard); |
941 | /// let guard = mutex.lock().await; |
942 | /// println!("2. contains: {:?}" , *guard); |
943 | /// guard |
944 | /// } |
945 | /// # |
946 | /// # #[tokio::main] |
947 | /// # async fn main() { |
948 | /// # let mutex = Mutex::new(0u32); |
949 | /// # let guard = mutex.lock().await; |
950 | /// # let _guard = unlock_and_relock(guard).await; |
951 | /// # } |
952 | /// ``` |
953 | #[inline ] |
954 | pub fn mutex(this: &Self) -> &'a Mutex<T> { |
955 | this.lock |
956 | } |
957 | } |
958 | |
959 | impl<T: ?Sized> Drop for MutexGuard<'_, T> { |
960 | fn drop(&mut self) { |
961 | self.lock.s.release(1); |
962 | |
963 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
964 | self.resource_span.in_scope(|| { |
965 | tracing::trace!( |
966 | target: "runtime::resource::state_update" , |
967 | locked = false, |
968 | ); |
969 | }); |
970 | } |
971 | } |
972 | |
973 | impl<T: ?Sized> Deref for MutexGuard<'_, T> { |
974 | type Target = T; |
975 | fn deref(&self) -> &Self::Target { |
976 | unsafe { &*self.lock.c.get() } |
977 | } |
978 | } |
979 | |
980 | impl<T: ?Sized> DerefMut for MutexGuard<'_, T> { |
981 | fn deref_mut(&mut self) -> &mut Self::Target { |
982 | unsafe { &mut *self.lock.c.get() } |
983 | } |
984 | } |
985 | |
986 | impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> { |
987 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
988 | fmt::Debug::fmt(&**self, f) |
989 | } |
990 | } |
991 | |
992 | impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> { |
993 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
994 | fmt::Display::fmt(&**self, f) |
995 | } |
996 | } |
997 | |
998 | // === impl OwnedMutexGuard === |
999 | |
1000 | impl<T: ?Sized> OwnedMutexGuard<T> { |
1001 | fn skip_drop(self) -> OwnedMutexGuardInner<T> { |
1002 | let me = mem::ManuallyDrop::new(self); |
1003 | // SAFETY: This duplicates the values in every field of the guard, then |
1004 | // forgets the originals, so in the end no value is duplicated. |
1005 | unsafe { |
1006 | OwnedMutexGuardInner { |
1007 | lock: ptr::read(&me.lock), |
1008 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1009 | resource_span: ptr::read(&me.resource_span), |
1010 | } |
1011 | } |
1012 | } |
1013 | |
1014 | /// Makes a new [`OwnedMappedMutexGuard`] for a component of the locked data. |
1015 | /// |
1016 | /// This operation cannot fail as the [`OwnedMutexGuard`] passed in already locked the mutex. |
1017 | /// |
1018 | /// This is an associated function that needs to be used as `OwnedMutexGuard::map(...)`. A method |
1019 | /// would interfere with methods of the same name on the contents of the locked data. |
1020 | /// |
1021 | /// # Examples |
1022 | /// |
1023 | /// ``` |
1024 | /// use tokio::sync::{Mutex, OwnedMutexGuard}; |
1025 | /// use std::sync::Arc; |
1026 | /// |
1027 | /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
1028 | /// struct Foo(u32); |
1029 | /// |
1030 | /// # #[tokio::main] |
1031 | /// # async fn main() { |
1032 | /// let foo = Arc::new(Mutex::new(Foo(1))); |
1033 | /// |
1034 | /// { |
1035 | /// let mut mapped = OwnedMutexGuard::map(foo.clone().lock_owned().await, |f| &mut f.0); |
1036 | /// *mapped = 2; |
1037 | /// } |
1038 | /// |
1039 | /// assert_eq!(Foo(2), *foo.lock().await); |
1040 | /// # } |
1041 | /// ``` |
1042 | /// |
1043 | /// [`OwnedMutexGuard`]: struct@OwnedMutexGuard |
1044 | /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard |
1045 | #[inline ] |
1046 | pub fn map<U, F>(mut this: Self, f: F) -> OwnedMappedMutexGuard<T, U> |
1047 | where |
1048 | U: ?Sized, |
1049 | F: FnOnce(&mut T) -> &mut U, |
1050 | { |
1051 | let data = f(&mut *this) as *mut U; |
1052 | let inner = this.skip_drop(); |
1053 | OwnedMappedMutexGuard { |
1054 | data, |
1055 | lock: inner.lock, |
1056 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1057 | resource_span: inner.resource_span, |
1058 | } |
1059 | } |
1060 | |
1061 | /// Attempts to make a new [`OwnedMappedMutexGuard`] for a component of the locked data. The |
1062 | /// original guard is returned if the closure returns `None`. |
1063 | /// |
1064 | /// This operation cannot fail as the [`OwnedMutexGuard`] passed in already locked the mutex. |
1065 | /// |
1066 | /// This is an associated function that needs to be used as `OwnedMutexGuard::try_map(...)`. A |
1067 | /// method would interfere with methods of the same name on the contents of the locked data. |
1068 | /// |
1069 | /// # Examples |
1070 | /// |
1071 | /// ``` |
1072 | /// use tokio::sync::{Mutex, OwnedMutexGuard}; |
1073 | /// use std::sync::Arc; |
1074 | /// |
1075 | /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
1076 | /// struct Foo(u32); |
1077 | /// |
1078 | /// # #[tokio::main] |
1079 | /// # async fn main() { |
1080 | /// let foo = Arc::new(Mutex::new(Foo(1))); |
1081 | /// |
1082 | /// { |
1083 | /// let mut mapped = OwnedMutexGuard::try_map(foo.clone().lock_owned().await, |f| Some(&mut f.0)) |
1084 | /// .expect("should not fail" ); |
1085 | /// *mapped = 2; |
1086 | /// } |
1087 | /// |
1088 | /// assert_eq!(Foo(2), *foo.lock().await); |
1089 | /// # } |
1090 | /// ``` |
1091 | /// |
1092 | /// [`OwnedMutexGuard`]: struct@OwnedMutexGuard |
1093 | /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard |
1094 | #[inline ] |
1095 | pub fn try_map<U, F>(mut this: Self, f: F) -> Result<OwnedMappedMutexGuard<T, U>, Self> |
1096 | where |
1097 | U: ?Sized, |
1098 | F: FnOnce(&mut T) -> Option<&mut U>, |
1099 | { |
1100 | let data = match f(&mut *this) { |
1101 | Some(data) => data as *mut U, |
1102 | None => return Err(this), |
1103 | }; |
1104 | let inner = this.skip_drop(); |
1105 | Ok(OwnedMappedMutexGuard { |
1106 | data, |
1107 | lock: inner.lock, |
1108 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1109 | resource_span: inner.resource_span, |
1110 | }) |
1111 | } |
1112 | |
1113 | /// Returns a reference to the original `Arc<Mutex>`. |
1114 | /// |
1115 | /// ``` |
1116 | /// use std::sync::Arc; |
1117 | /// use tokio::sync::{Mutex, OwnedMutexGuard}; |
1118 | /// |
1119 | /// async fn unlock_and_relock(guard: OwnedMutexGuard<u32>) -> OwnedMutexGuard<u32> { |
1120 | /// println!("1. contains: {:?}" , *guard); |
1121 | /// let mutex: Arc<Mutex<u32>> = OwnedMutexGuard::mutex(&guard).clone(); |
1122 | /// drop(guard); |
1123 | /// let guard = mutex.lock_owned().await; |
1124 | /// println!("2. contains: {:?}" , *guard); |
1125 | /// guard |
1126 | /// } |
1127 | /// # |
1128 | /// # #[tokio::main] |
1129 | /// # async fn main() { |
1130 | /// # let mutex = Arc::new(Mutex::new(0u32)); |
1131 | /// # let guard = mutex.lock_owned().await; |
1132 | /// # unlock_and_relock(guard).await; |
1133 | /// # } |
1134 | /// ``` |
1135 | #[inline ] |
1136 | pub fn mutex(this: &Self) -> &Arc<Mutex<T>> { |
1137 | &this.lock |
1138 | } |
1139 | } |
1140 | |
1141 | impl<T: ?Sized> Drop for OwnedMutexGuard<T> { |
1142 | fn drop(&mut self) { |
1143 | self.lock.s.release(1); |
1144 | |
1145 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1146 | self.resource_span.in_scope(|| { |
1147 | tracing::trace!( |
1148 | target: "runtime::resource::state_update" , |
1149 | locked = false, |
1150 | ); |
1151 | }); |
1152 | } |
1153 | } |
1154 | |
1155 | impl<T: ?Sized> Deref for OwnedMutexGuard<T> { |
1156 | type Target = T; |
1157 | fn deref(&self) -> &Self::Target { |
1158 | unsafe { &*self.lock.c.get() } |
1159 | } |
1160 | } |
1161 | |
1162 | impl<T: ?Sized> DerefMut for OwnedMutexGuard<T> { |
1163 | fn deref_mut(&mut self) -> &mut Self::Target { |
1164 | unsafe { &mut *self.lock.c.get() } |
1165 | } |
1166 | } |
1167 | |
1168 | impl<T: ?Sized + fmt::Debug> fmt::Debug for OwnedMutexGuard<T> { |
1169 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1170 | fmt::Debug::fmt(&**self, f) |
1171 | } |
1172 | } |
1173 | |
1174 | impl<T: ?Sized + fmt::Display> fmt::Display for OwnedMutexGuard<T> { |
1175 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1176 | fmt::Display::fmt(&**self, f) |
1177 | } |
1178 | } |
1179 | |
1180 | // === impl MappedMutexGuard === |
1181 | |
1182 | impl<'a, T: ?Sized> MappedMutexGuard<'a, T> { |
1183 | fn skip_drop(self) -> MappedMutexGuardInner<'a, T> { |
1184 | let me = mem::ManuallyDrop::new(self); |
1185 | MappedMutexGuardInner { |
1186 | s: me.s, |
1187 | data: me.data, |
1188 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1189 | resource_span: unsafe { std::ptr::read(&me.resource_span) }, |
1190 | } |
1191 | } |
1192 | |
1193 | /// Makes a new [`MappedMutexGuard`] for a component of the locked data. |
1194 | /// |
1195 | /// This operation cannot fail as the [`MappedMutexGuard`] passed in already locked the mutex. |
1196 | /// |
1197 | /// This is an associated function that needs to be used as `MappedMutexGuard::map(...)`. A |
1198 | /// method would interfere with methods of the same name on the contents of the locked data. |
1199 | /// |
1200 | /// [`MappedMutexGuard`]: struct@MappedMutexGuard |
1201 | #[inline ] |
1202 | pub fn map<U, F>(mut this: Self, f: F) -> MappedMutexGuard<'a, U> |
1203 | where |
1204 | F: FnOnce(&mut T) -> &mut U, |
1205 | { |
1206 | let data = f(&mut *this) as *mut U; |
1207 | let inner = this.skip_drop(); |
1208 | MappedMutexGuard { |
1209 | s: inner.s, |
1210 | data, |
1211 | marker: PhantomData, |
1212 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1213 | resource_span: inner.resource_span, |
1214 | } |
1215 | } |
1216 | |
1217 | /// Attempts to make a new [`MappedMutexGuard`] for a component of the locked data. The |
1218 | /// original guard is returned if the closure returns `None`. |
1219 | /// |
1220 | /// This operation cannot fail as the [`MappedMutexGuard`] passed in already locked the mutex. |
1221 | /// |
1222 | /// This is an associated function that needs to be used as `MappedMutexGuard::try_map(...)`. A |
1223 | /// method would interfere with methods of the same name on the contents of the locked data. |
1224 | /// |
1225 | /// [`MappedMutexGuard`]: struct@MappedMutexGuard |
1226 | #[inline ] |
1227 | pub fn try_map<U, F>(mut this: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self> |
1228 | where |
1229 | F: FnOnce(&mut T) -> Option<&mut U>, |
1230 | { |
1231 | let data = match f(&mut *this) { |
1232 | Some(data) => data as *mut U, |
1233 | None => return Err(this), |
1234 | }; |
1235 | let inner = this.skip_drop(); |
1236 | Ok(MappedMutexGuard { |
1237 | s: inner.s, |
1238 | data, |
1239 | marker: PhantomData, |
1240 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1241 | resource_span: inner.resource_span, |
1242 | }) |
1243 | } |
1244 | } |
1245 | |
1246 | impl<'a, T: ?Sized> Drop for MappedMutexGuard<'a, T> { |
1247 | fn drop(&mut self) { |
1248 | self.s.release(1); |
1249 | |
1250 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1251 | self.resource_span.in_scope(|| { |
1252 | tracing::trace!( |
1253 | target: "runtime::resource::state_update" , |
1254 | locked = false, |
1255 | ); |
1256 | }); |
1257 | } |
1258 | } |
1259 | |
1260 | impl<'a, T: ?Sized> Deref for MappedMutexGuard<'a, T> { |
1261 | type Target = T; |
1262 | fn deref(&self) -> &Self::Target { |
1263 | unsafe { &*self.data } |
1264 | } |
1265 | } |
1266 | |
1267 | impl<'a, T: ?Sized> DerefMut for MappedMutexGuard<'a, T> { |
1268 | fn deref_mut(&mut self) -> &mut Self::Target { |
1269 | unsafe { &mut *self.data } |
1270 | } |
1271 | } |
1272 | |
1273 | impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MappedMutexGuard<'a, T> { |
1274 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1275 | fmt::Debug::fmt(&**self, f) |
1276 | } |
1277 | } |
1278 | |
1279 | impl<'a, T: ?Sized + fmt::Display> fmt::Display for MappedMutexGuard<'a, T> { |
1280 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1281 | fmt::Display::fmt(&**self, f) |
1282 | } |
1283 | } |
1284 | |
1285 | // === impl OwnedMappedMutexGuard === |
1286 | |
1287 | impl<T: ?Sized, U: ?Sized> OwnedMappedMutexGuard<T, U> { |
1288 | fn skip_drop(self) -> OwnedMappedMutexGuardInner<T, U> { |
1289 | let me = mem::ManuallyDrop::new(self); |
1290 | // SAFETY: This duplicates the values in every field of the guard, then |
1291 | // forgets the originals, so in the end no value is duplicated. |
1292 | unsafe { |
1293 | OwnedMappedMutexGuardInner { |
1294 | data: me.data, |
1295 | lock: ptr::read(&me.lock), |
1296 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1297 | resource_span: ptr::read(&me.resource_span), |
1298 | } |
1299 | } |
1300 | } |
1301 | |
1302 | /// Makes a new [`OwnedMappedMutexGuard`] for a component of the locked data. |
1303 | /// |
1304 | /// This operation cannot fail as the [`OwnedMappedMutexGuard`] passed in already locked the mutex. |
1305 | /// |
1306 | /// This is an associated function that needs to be used as `OwnedMappedMutexGuard::map(...)`. A method |
1307 | /// would interfere with methods of the same name on the contents of the locked data. |
1308 | /// |
1309 | /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard |
1310 | #[inline ] |
1311 | pub fn map<S, F>(mut this: Self, f: F) -> OwnedMappedMutexGuard<T, S> |
1312 | where |
1313 | F: FnOnce(&mut U) -> &mut S, |
1314 | { |
1315 | let data = f(&mut *this) as *mut S; |
1316 | let inner = this.skip_drop(); |
1317 | OwnedMappedMutexGuard { |
1318 | data, |
1319 | lock: inner.lock, |
1320 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1321 | resource_span: inner.resource_span, |
1322 | } |
1323 | } |
1324 | |
1325 | /// Attempts to make a new [`OwnedMappedMutexGuard`] for a component of the locked data. The |
1326 | /// original guard is returned if the closure returns `None`. |
1327 | /// |
1328 | /// This operation cannot fail as the [`OwnedMutexGuard`] passed in already locked the mutex. |
1329 | /// |
1330 | /// This is an associated function that needs to be used as `OwnedMutexGuard::try_map(...)`. A |
1331 | /// method would interfere with methods of the same name on the contents of the locked data. |
1332 | /// |
1333 | /// [`OwnedMutexGuard`]: struct@OwnedMutexGuard |
1334 | /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard |
1335 | #[inline ] |
1336 | pub fn try_map<S, F>(mut this: Self, f: F) -> Result<OwnedMappedMutexGuard<T, S>, Self> |
1337 | where |
1338 | F: FnOnce(&mut U) -> Option<&mut S>, |
1339 | { |
1340 | let data = match f(&mut *this) { |
1341 | Some(data) => data as *mut S, |
1342 | None => return Err(this), |
1343 | }; |
1344 | let inner = this.skip_drop(); |
1345 | Ok(OwnedMappedMutexGuard { |
1346 | data, |
1347 | lock: inner.lock, |
1348 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1349 | resource_span: inner.resource_span, |
1350 | }) |
1351 | } |
1352 | } |
1353 | |
1354 | impl<T: ?Sized, U: ?Sized> Drop for OwnedMappedMutexGuard<T, U> { |
1355 | fn drop(&mut self) { |
1356 | self.lock.s.release(1); |
1357 | |
1358 | #[cfg (all(tokio_unstable, feature = "tracing" ))] |
1359 | self.resource_span.in_scope(|| { |
1360 | tracing::trace!( |
1361 | target: "runtime::resource::state_update" , |
1362 | locked = false, |
1363 | ); |
1364 | }); |
1365 | } |
1366 | } |
1367 | |
1368 | impl<T: ?Sized, U: ?Sized> Deref for OwnedMappedMutexGuard<T, U> { |
1369 | type Target = U; |
1370 | fn deref(&self) -> &Self::Target { |
1371 | unsafe { &*self.data } |
1372 | } |
1373 | } |
1374 | |
1375 | impl<T: ?Sized, U: ?Sized> DerefMut for OwnedMappedMutexGuard<T, U> { |
1376 | fn deref_mut(&mut self) -> &mut Self::Target { |
1377 | unsafe { &mut *self.data } |
1378 | } |
1379 | } |
1380 | |
1381 | impl<T: ?Sized, U: ?Sized + fmt::Debug> fmt::Debug for OwnedMappedMutexGuard<T, U> { |
1382 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1383 | fmt::Debug::fmt(&**self, f) |
1384 | } |
1385 | } |
1386 | |
1387 | impl<T: ?Sized, U: ?Sized + fmt::Display> fmt::Display for OwnedMappedMutexGuard<T, U> { |
1388 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1389 | fmt::Display::fmt(&**self, f) |
1390 | } |
1391 | } |
1392 | |