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