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/// # 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
129pub 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"]
147pub 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]
171pub 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"]
186pub 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"]
205pub 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.
217struct 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.
225struct 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.
234struct 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.
244struct 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>.
254unsafe impl<T> Send for Mutex<T> where T: ?Sized + Send {}
255unsafe impl<T> Sync for Mutex<T> where T: ?Sized + Send {}
256unsafe impl<T> Sync for MutexGuard<'_, T> where T: ?Sized + Send + Sync {}
257unsafe impl<T> Sync for OwnedMutexGuard<T> where T: ?Sized + Send + Sync {}
258unsafe impl<'a, T> Sync for MappedMutexGuard<'a, T> where T: ?Sized + Sync + 'a {}
259unsafe impl<'a, T> Send for MappedMutexGuard<'a, T> where T: ?Sized + Send + 'a {}
260
261unsafe impl<T, U> Sync for OwnedMappedMutexGuard<T, U>
262where
263 T: ?Sized + Send + Sync,
264 U: ?Sized + Send + Sync,
265{
266}
267unsafe impl<T, U> Send for OwnedMappedMutexGuard<T, U>
268where
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)]
289pub struct TryLockError(pub(super) ());
290
291impl fmt::Display for TryLockError {
292 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
293 write!(fmt, "operation would block")
294 }
295}
296
297impl Error for TryLockError {}
298
299#[test]
300#[cfg(not(loom))]
301fn 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
323impl<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
790impl<T> From<T> for Mutex<T> {
791 fn from(s: T) -> Self {
792 Self::new(s)
793 }
794}
795
796impl<T> Default for Mutex<T>
797where
798 T: Default,
799{
800 fn default() -> Self {
801 Self::new(T::default())
802 }
803}
804
805impl<T: ?Sized> std::fmt::Debug for Mutex<T>
806where
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
821impl<'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
959impl<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
973impl<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
980impl<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
986impl<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
992impl<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
1000impl<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
1141impl<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
1155impl<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
1162impl<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
1168impl<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
1174impl<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
1182impl<'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
1246impl<'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
1260impl<'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
1267impl<'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
1273impl<'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
1279impl<'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
1287impl<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
1354impl<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
1368impl<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
1375impl<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
1381impl<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
1387impl<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