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 12 and 19.
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 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result292 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))]
bounds()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]
new(t: T) -> Self where T: Sized,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 "runtime.resource",
344 concrete_type = "Mutex",
345 kind = "Sync",
346 loc.file = location.file(),
347 loc.line = location.line(),
348 loc.col = location.column(),
349 )
350 };
351
352 #[cfg(all(tokio_unstable, feature = "tracing"))]
353 let s = resource_span.in_scope(|| {
354 tracing::trace!(
355 target: "runtime::resource::state_update",
356 locked = false,
357 );
358 semaphore::Semaphore::new(1)
359 });
360
361 #[cfg(any(not(tokio_unstable), not(feature = "tracing")))]
362 let s = semaphore::Semaphore::new(1);
363
364 Self {
365 c: UnsafeCell::new(t),
366 s,
367 #[cfg(all(tokio_unstable, feature = "tracing"))]
368 resource_span,
369 }
370 }
371
372 /// Creates a new lock in an unlocked state ready for use.
373 ///
374 /// # Examples
375 ///
376 /// ```
377 /// use tokio::sync::Mutex;
378 ///
379 /// static LOCK: Mutex<i32> = Mutex::const_new(5);
380 /// ```
381 #[cfg(not(all(loom, test)))]
const_new(t: T) -> Self where T: Sized,382 pub const fn const_new(t: T) -> Self
383 where
384 T: Sized,
385 {
386 Self {
387 c: UnsafeCell::new(t),
388 s: semaphore::Semaphore::const_new(1),
389 #[cfg(all(tokio_unstable, feature = "tracing"))]
390 resource_span: tracing::Span::none(),
391 }
392 }
393
394 /// Locks this mutex, causing the current task to yield until the lock has
395 /// been acquired. When the lock has been acquired, function returns a
396 /// [`MutexGuard`].
397 ///
398 /// # Cancel safety
399 ///
400 /// This method uses a queue to fairly distribute locks in the order they
401 /// were requested. Cancelling a call to `lock` makes you lose your place in
402 /// the queue.
403 ///
404 /// # Examples
405 ///
406 /// ```
407 /// use tokio::sync::Mutex;
408 ///
409 /// #[tokio::main]
410 /// async fn main() {
411 /// let mutex = Mutex::new(1);
412 ///
413 /// let mut n = mutex.lock().await;
414 /// *n = 2;
415 /// }
416 /// ```
lock(&self) -> MutexGuard<'_, T>417 pub async fn lock(&self) -> MutexGuard<'_, T> {
418 let acquire_fut = async {
419 self.acquire().await;
420
421 MutexGuard {
422 lock: self,
423 #[cfg(all(tokio_unstable, feature = "tracing"))]
424 resource_span: self.resource_span.clone(),
425 }
426 };
427
428 #[cfg(all(tokio_unstable, feature = "tracing"))]
429 let acquire_fut = trace::async_op(
430 move || acquire_fut,
431 self.resource_span.clone(),
432 "Mutex::lock",
433 "poll",
434 false,
435 );
436
437 #[allow(clippy::let_and_return)] // this lint triggers when disabling tracing
438 let guard = acquire_fut.await;
439
440 #[cfg(all(tokio_unstable, feature = "tracing"))]
441 self.resource_span.in_scope(|| {
442 tracing::trace!(
443 target: "runtime::resource::state_update",
444 locked = true,
445 );
446 });
447
448 guard
449 }
450
451 /// Blockingly locks this `Mutex`. When the lock has been acquired, function returns a
452 /// [`MutexGuard`].
453 ///
454 /// This method is intended for use cases where you
455 /// need to use this mutex in asynchronous code as well as in synchronous code.
456 ///
457 /// # Panics
458 ///
459 /// This function panics if called within an asynchronous execution context.
460 ///
461 /// - If you find yourself in an asynchronous execution context and needing
462 /// to call some (synchronous) function which performs one of these
463 /// `blocking_` operations, then consider wrapping that call inside
464 /// [`spawn_blocking()`][crate::runtime::Handle::spawn_blocking]
465 /// (or [`block_in_place()`][crate::task::block_in_place]).
466 ///
467 /// # Examples
468 ///
469 /// ```
470 /// use std::sync::Arc;
471 /// use tokio::sync::Mutex;
472 ///
473 /// #[tokio::main]
474 /// async fn main() {
475 /// let mutex = Arc::new(Mutex::new(1));
476 /// let lock = mutex.lock().await;
477 ///
478 /// let mutex1 = Arc::clone(&mutex);
479 /// let blocking_task = tokio::task::spawn_blocking(move || {
480 /// // This shall block until the `lock` is released.
481 /// let mut n = mutex1.blocking_lock();
482 /// *n = 2;
483 /// });
484 ///
485 /// assert_eq!(*lock, 1);
486 /// // Release the lock.
487 /// drop(lock);
488 ///
489 /// // Await the completion of the blocking task.
490 /// blocking_task.await.unwrap();
491 ///
492 /// // Assert uncontended.
493 /// let n = mutex.try_lock().unwrap();
494 /// assert_eq!(*n, 2);
495 /// }
496 ///
497 /// ```
498 #[track_caller]
499 #[cfg(feature = "sync")]
500 #[cfg_attr(docsrs, doc(alias = "lock_blocking"))]
blocking_lock(&self) -> MutexGuard<'_, T>501 pub fn blocking_lock(&self) -> MutexGuard<'_, T> {
502 crate::future::block_on(self.lock())
503 }
504
505 /// Blockingly locks this `Mutex`. When the lock has been acquired, function returns an
506 /// [`OwnedMutexGuard`].
507 ///
508 /// This method is identical to [`Mutex::blocking_lock`], except that the returned
509 /// guard references the `Mutex` with an [`Arc`] rather than by borrowing
510 /// it. Therefore, the `Mutex` must be wrapped in an `Arc` to call this
511 /// method, and the guard will live for the `'static` lifetime, as it keeps
512 /// the `Mutex` alive by holding an `Arc`.
513 ///
514 /// # Panics
515 ///
516 /// This function panics if called within an asynchronous execution context.
517 ///
518 /// - If you find yourself in an asynchronous execution context and needing
519 /// to call some (synchronous) function which performs one of these
520 /// `blocking_` operations, then consider wrapping that call inside
521 /// [`spawn_blocking()`][crate::runtime::Handle::spawn_blocking]
522 /// (or [`block_in_place()`][crate::task::block_in_place]).
523 ///
524 /// # Examples
525 ///
526 /// ```
527 /// use std::sync::Arc;
528 /// use tokio::sync::Mutex;
529 ///
530 /// #[tokio::main]
531 /// async fn main() {
532 /// let mutex = Arc::new(Mutex::new(1));
533 /// let lock = mutex.lock().await;
534 ///
535 /// let mutex1 = Arc::clone(&mutex);
536 /// let blocking_task = tokio::task::spawn_blocking(move || {
537 /// // This shall block until the `lock` is released.
538 /// let mut n = mutex1.blocking_lock_owned();
539 /// *n = 2;
540 /// });
541 ///
542 /// assert_eq!(*lock, 1);
543 /// // Release the lock.
544 /// drop(lock);
545 ///
546 /// // Await the completion of the blocking task.
547 /// blocking_task.await.unwrap();
548 ///
549 /// // Assert uncontended.
550 /// let n = mutex.try_lock().unwrap();
551 /// assert_eq!(*n, 2);
552 /// }
553 ///
554 /// ```
555 #[track_caller]
556 #[cfg(feature = "sync")]
blocking_lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T>557 pub fn blocking_lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T> {
558 crate::future::block_on(self.lock_owned())
559 }
560
561 /// Locks this mutex, causing the current task to yield until the lock has
562 /// been acquired. When the lock has been acquired, this returns an
563 /// [`OwnedMutexGuard`].
564 ///
565 /// This method is identical to [`Mutex::lock`], except that the returned
566 /// guard references the `Mutex` with an [`Arc`] rather than by borrowing
567 /// it. Therefore, the `Mutex` must be wrapped in an `Arc` to call this
568 /// method, and the guard will live for the `'static` lifetime, as it keeps
569 /// the `Mutex` alive by holding an `Arc`.
570 ///
571 /// # Cancel safety
572 ///
573 /// This method uses a queue to fairly distribute locks in the order they
574 /// were requested. Cancelling a call to `lock_owned` makes you lose your
575 /// place in the queue.
576 ///
577 /// # Examples
578 ///
579 /// ```
580 /// use tokio::sync::Mutex;
581 /// use std::sync::Arc;
582 ///
583 /// #[tokio::main]
584 /// async fn main() {
585 /// let mutex = Arc::new(Mutex::new(1));
586 ///
587 /// let mut n = mutex.clone().lock_owned().await;
588 /// *n = 2;
589 /// }
590 /// ```
591 ///
592 /// [`Arc`]: std::sync::Arc
lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T>593 pub async fn lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T> {
594 #[cfg(all(tokio_unstable, feature = "tracing"))]
595 let resource_span = self.resource_span.clone();
596
597 let acquire_fut = async {
598 self.acquire().await;
599
600 OwnedMutexGuard {
601 #[cfg(all(tokio_unstable, feature = "tracing"))]
602 resource_span: self.resource_span.clone(),
603 lock: self,
604 }
605 };
606
607 #[cfg(all(tokio_unstable, feature = "tracing"))]
608 let acquire_fut = trace::async_op(
609 move || acquire_fut,
610 resource_span,
611 "Mutex::lock_owned",
612 "poll",
613 false,
614 );
615
616 #[allow(clippy::let_and_return)] // this lint triggers when disabling tracing
617 let guard = acquire_fut.await;
618
619 #[cfg(all(tokio_unstable, feature = "tracing"))]
620 guard.resource_span.in_scope(|| {
621 tracing::trace!(
622 target: "runtime::resource::state_update",
623 locked = true,
624 );
625 });
626
627 guard
628 }
629
acquire(&self)630 async fn acquire(&self) {
631 crate::trace::async_trace_leaf().await;
632
633 self.s.acquire(1).await.unwrap_or_else(|_| {
634 // The semaphore was closed. but, we never explicitly close it, and
635 // we own it exclusively, which means that this can never happen.
636 unreachable!()
637 });
638 }
639
640 /// Attempts to acquire the lock, and returns [`TryLockError`] if the
641 /// lock is currently held somewhere else.
642 ///
643 /// [`TryLockError`]: TryLockError
644 /// # Examples
645 ///
646 /// ```
647 /// use tokio::sync::Mutex;
648 /// # async fn dox() -> Result<(), tokio::sync::TryLockError> {
649 ///
650 /// let mutex = Mutex::new(1);
651 ///
652 /// let n = mutex.try_lock()?;
653 /// assert_eq!(*n, 1);
654 /// # Ok(())
655 /// # }
656 /// ```
try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError>657 pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError> {
658 match self.s.try_acquire(1) {
659 Ok(_) => {
660 let guard = MutexGuard {
661 lock: self,
662 #[cfg(all(tokio_unstable, feature = "tracing"))]
663 resource_span: self.resource_span.clone(),
664 };
665
666 #[cfg(all(tokio_unstable, feature = "tracing"))]
667 self.resource_span.in_scope(|| {
668 tracing::trace!(
669 target: "runtime::resource::state_update",
670 locked = true,
671 );
672 });
673
674 Ok(guard)
675 }
676 Err(_) => Err(TryLockError(())),
677 }
678 }
679
680 /// Returns a mutable reference to the underlying data.
681 ///
682 /// Since this call borrows the `Mutex` mutably, no actual locking needs to
683 /// take place -- the mutable borrow statically guarantees no locks exist.
684 ///
685 /// # Examples
686 ///
687 /// ```
688 /// use tokio::sync::Mutex;
689 ///
690 /// fn main() {
691 /// let mut mutex = Mutex::new(1);
692 ///
693 /// let n = mutex.get_mut();
694 /// *n = 2;
695 /// }
696 /// ```
get_mut(&mut self) -> &mut T697 pub fn get_mut(&mut self) -> &mut T {
698 unsafe {
699 // Safety: This is https://github.com/rust-lang/rust/pull/76936
700 &mut *self.c.get()
701 }
702 }
703
704 /// Attempts to acquire the lock, and returns [`TryLockError`] if the lock
705 /// is currently held somewhere else.
706 ///
707 /// This method is identical to [`Mutex::try_lock`], except that the
708 /// returned guard references the `Mutex` with an [`Arc`] rather than by
709 /// borrowing it. Therefore, the `Mutex` must be wrapped in an `Arc` to call
710 /// this method, and the guard will live for the `'static` lifetime, as it
711 /// keeps the `Mutex` alive by holding an `Arc`.
712 ///
713 /// [`TryLockError`]: TryLockError
714 /// [`Arc`]: std::sync::Arc
715 /// # Examples
716 ///
717 /// ```
718 /// use tokio::sync::Mutex;
719 /// use std::sync::Arc;
720 /// # async fn dox() -> Result<(), tokio::sync::TryLockError> {
721 ///
722 /// let mutex = Arc::new(Mutex::new(1));
723 ///
724 /// let n = mutex.clone().try_lock_owned()?;
725 /// assert_eq!(*n, 1);
726 /// # Ok(())
727 /// # }
try_lock_owned(self: Arc<Self>) -> Result<OwnedMutexGuard<T>, TryLockError>728 pub fn try_lock_owned(self: Arc<Self>) -> Result<OwnedMutexGuard<T>, TryLockError> {
729 match self.s.try_acquire(1) {
730 Ok(_) => {
731 let guard = OwnedMutexGuard {
732 #[cfg(all(tokio_unstable, feature = "tracing"))]
733 resource_span: self.resource_span.clone(),
734 lock: self,
735 };
736
737 #[cfg(all(tokio_unstable, feature = "tracing"))]
738 guard.resource_span.in_scope(|| {
739 tracing::trace!(
740 target: "runtime::resource::state_update",
741 locked = true,
742 );
743 });
744
745 Ok(guard)
746 }
747 Err(_) => Err(TryLockError(())),
748 }
749 }
750
751 /// Consumes the mutex, returning the underlying data.
752 /// # Examples
753 ///
754 /// ```
755 /// use tokio::sync::Mutex;
756 ///
757 /// #[tokio::main]
758 /// async fn main() {
759 /// let mutex = Mutex::new(1);
760 ///
761 /// let n = mutex.into_inner();
762 /// assert_eq!(n, 1);
763 /// }
764 /// ```
into_inner(self) -> T where T: Sized,765 pub fn into_inner(self) -> T
766 where
767 T: Sized,
768 {
769 self.c.into_inner()
770 }
771 }
772
773 impl<T> From<T> for Mutex<T> {
from(s: T) -> Self774 fn from(s: T) -> Self {
775 Self::new(s)
776 }
777 }
778
779 impl<T> Default for Mutex<T>
780 where
781 T: Default,
782 {
default() -> Self783 fn default() -> Self {
784 Self::new(T::default())
785 }
786 }
787
788 impl<T: ?Sized> std::fmt::Debug for Mutex<T>
789 where
790 T: std::fmt::Debug,
791 {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result792 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
793 let mut d = f.debug_struct("Mutex");
794 match self.try_lock() {
795 Ok(inner) => d.field("data", &&*inner),
796 Err(_) => d.field("data", &format_args!("<locked>")),
797 };
798 d.finish()
799 }
800 }
801
802 // === impl MutexGuard ===
803
804 impl<'a, T: ?Sized> MutexGuard<'a, T> {
skip_drop(self) -> MutexGuardInner<'a, T>805 fn skip_drop(self) -> MutexGuardInner<'a, T> {
806 let me = mem::ManuallyDrop::new(self);
807 // SAFETY: This duplicates the `resource_span` and then forgets the
808 // original. In the end, we have not duplicated or forgotten any values.
809 MutexGuardInner {
810 #[cfg(all(tokio_unstable, feature = "tracing"))]
811 resource_span: unsafe { std::ptr::read(&me.resource_span) },
812 lock: me.lock,
813 }
814 }
815
816 /// Makes a new [`MappedMutexGuard`] for a component of the locked data.
817 ///
818 /// This operation cannot fail as the [`MutexGuard`] passed in already locked the mutex.
819 ///
820 /// This is an associated function that needs to be used as `MutexGuard::map(...)`. A method
821 /// would interfere with methods of the same name on the contents of the locked data.
822 ///
823 /// # Examples
824 ///
825 /// ```
826 /// use tokio::sync::{Mutex, MutexGuard};
827 ///
828 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
829 /// struct Foo(u32);
830 ///
831 /// # #[tokio::main]
832 /// # async fn main() {
833 /// let foo = Mutex::new(Foo(1));
834 ///
835 /// {
836 /// let mut mapped = MutexGuard::map(foo.lock().await, |f| &mut f.0);
837 /// *mapped = 2;
838 /// }
839 ///
840 /// assert_eq!(Foo(2), *foo.lock().await);
841 /// # }
842 /// ```
843 ///
844 /// [`MutexGuard`]: struct@MutexGuard
845 /// [`MappedMutexGuard`]: struct@MappedMutexGuard
846 #[inline]
map<U, F>(mut this: Self, f: F) -> MappedMutexGuard<'a, U> where F: FnOnce(&mut T) -> &mut U,847 pub fn map<U, F>(mut this: Self, f: F) -> MappedMutexGuard<'a, U>
848 where
849 F: FnOnce(&mut T) -> &mut U,
850 {
851 let data = f(&mut *this) as *mut U;
852 let inner = this.skip_drop();
853 MappedMutexGuard {
854 s: &inner.lock.s,
855 data,
856 marker: PhantomData,
857 #[cfg(all(tokio_unstable, feature = "tracing"))]
858 resource_span: inner.resource_span,
859 }
860 }
861
862 /// Attempts to make a new [`MappedMutexGuard`] for a component of the locked data. The
863 /// original guard is returned if the closure returns `None`.
864 ///
865 /// This operation cannot fail as the [`MutexGuard`] passed in already locked the mutex.
866 ///
867 /// This is an associated function that needs to be used as `MutexGuard::try_map(...)`. A
868 /// method would interfere with methods of the same name on the contents of the locked data.
869 ///
870 /// # Examples
871 ///
872 /// ```
873 /// use tokio::sync::{Mutex, MutexGuard};
874 ///
875 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
876 /// struct Foo(u32);
877 ///
878 /// # #[tokio::main]
879 /// # async fn main() {
880 /// let foo = Mutex::new(Foo(1));
881 ///
882 /// {
883 /// let mut mapped = MutexGuard::try_map(foo.lock().await, |f| Some(&mut f.0))
884 /// .expect("should not fail");
885 /// *mapped = 2;
886 /// }
887 ///
888 /// assert_eq!(Foo(2), *foo.lock().await);
889 /// # }
890 /// ```
891 ///
892 /// [`MutexGuard`]: struct@MutexGuard
893 /// [`MappedMutexGuard`]: struct@MappedMutexGuard
894 #[inline]
try_map<U, F>(mut this: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>,895 pub fn try_map<U, F>(mut this: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
896 where
897 F: FnOnce(&mut T) -> Option<&mut U>,
898 {
899 let data = match f(&mut *this) {
900 Some(data) => data as *mut U,
901 None => return Err(this),
902 };
903 let inner = this.skip_drop();
904 Ok(MappedMutexGuard {
905 s: &inner.lock.s,
906 data,
907 marker: PhantomData,
908 #[cfg(all(tokio_unstable, feature = "tracing"))]
909 resource_span: inner.resource_span,
910 })
911 }
912
913 /// Returns a reference to the original `Mutex`.
914 ///
915 /// ```
916 /// use tokio::sync::{Mutex, MutexGuard};
917 ///
918 /// async fn unlock_and_relock<'l>(guard: MutexGuard<'l, u32>) -> MutexGuard<'l, u32> {
919 /// println!("1. contains: {:?}", *guard);
920 /// let mutex = MutexGuard::mutex(&guard);
921 /// drop(guard);
922 /// let guard = mutex.lock().await;
923 /// println!("2. contains: {:?}", *guard);
924 /// guard
925 /// }
926 /// #
927 /// # #[tokio::main]
928 /// # async fn main() {
929 /// # let mutex = Mutex::new(0u32);
930 /// # let guard = mutex.lock().await;
931 /// # let _guard = unlock_and_relock(guard).await;
932 /// # }
933 /// ```
934 #[inline]
mutex(this: &Self) -> &'a Mutex<T>935 pub fn mutex(this: &Self) -> &'a Mutex<T> {
936 this.lock
937 }
938 }
939
940 impl<T: ?Sized> Drop for MutexGuard<'_, T> {
drop(&mut self)941 fn drop(&mut self) {
942 self.lock.s.release(1);
943
944 #[cfg(all(tokio_unstable, feature = "tracing"))]
945 self.resource_span.in_scope(|| {
946 tracing::trace!(
947 target: "runtime::resource::state_update",
948 locked = false,
949 );
950 });
951 }
952 }
953
954 impl<T: ?Sized> Deref for MutexGuard<'_, T> {
955 type Target = T;
deref(&self) -> &Self::Target956 fn deref(&self) -> &Self::Target {
957 unsafe { &*self.lock.c.get() }
958 }
959 }
960
961 impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
deref_mut(&mut self) -> &mut Self::Target962 fn deref_mut(&mut self) -> &mut Self::Target {
963 unsafe { &mut *self.lock.c.get() }
964 }
965 }
966
967 impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result968 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
969 fmt::Debug::fmt(&**self, f)
970 }
971 }
972
973 impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result974 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
975 fmt::Display::fmt(&**self, f)
976 }
977 }
978
979 // === impl OwnedMutexGuard ===
980
981 impl<T: ?Sized> OwnedMutexGuard<T> {
skip_drop(self) -> OwnedMutexGuardInner<T>982 fn skip_drop(self) -> OwnedMutexGuardInner<T> {
983 let me = mem::ManuallyDrop::new(self);
984 // SAFETY: This duplicates the values in every field of the guard, then
985 // forgets the originals, so in the end no value is duplicated.
986 unsafe {
987 OwnedMutexGuardInner {
988 lock: ptr::read(&me.lock),
989 #[cfg(all(tokio_unstable, feature = "tracing"))]
990 resource_span: ptr::read(&me.resource_span),
991 }
992 }
993 }
994
995 /// Makes a new [`OwnedMappedMutexGuard`] for a component of the locked data.
996 ///
997 /// This operation cannot fail as the [`OwnedMutexGuard`] passed in already locked the mutex.
998 ///
999 /// This is an associated function that needs to be used as `OwnedMutexGuard::map(...)`. A method
1000 /// would interfere with methods of the same name on the contents of the locked data.
1001 ///
1002 /// # Examples
1003 ///
1004 /// ```
1005 /// use tokio::sync::{Mutex, OwnedMutexGuard};
1006 /// use std::sync::Arc;
1007 ///
1008 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1009 /// struct Foo(u32);
1010 ///
1011 /// # #[tokio::main]
1012 /// # async fn main() {
1013 /// let foo = Arc::new(Mutex::new(Foo(1)));
1014 ///
1015 /// {
1016 /// let mut mapped = OwnedMutexGuard::map(foo.clone().lock_owned().await, |f| &mut f.0);
1017 /// *mapped = 2;
1018 /// }
1019 ///
1020 /// assert_eq!(Foo(2), *foo.lock().await);
1021 /// # }
1022 /// ```
1023 ///
1024 /// [`OwnedMutexGuard`]: struct@OwnedMutexGuard
1025 /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard
1026 #[inline]
map<U, F>(mut this: Self, f: F) -> OwnedMappedMutexGuard<T, U> where F: FnOnce(&mut T) -> &mut U,1027 pub fn map<U, F>(mut this: Self, f: F) -> OwnedMappedMutexGuard<T, U>
1028 where
1029 F: FnOnce(&mut T) -> &mut U,
1030 {
1031 let data = f(&mut *this) as *mut U;
1032 let inner = this.skip_drop();
1033 OwnedMappedMutexGuard {
1034 data,
1035 lock: inner.lock,
1036 #[cfg(all(tokio_unstable, feature = "tracing"))]
1037 resource_span: inner.resource_span,
1038 }
1039 }
1040
1041 /// Attempts to make a new [`OwnedMappedMutexGuard`] for a component of the locked data. The
1042 /// original guard is returned if the closure returns `None`.
1043 ///
1044 /// This operation cannot fail as the [`OwnedMutexGuard`] passed in already locked the mutex.
1045 ///
1046 /// This is an associated function that needs to be used as `OwnedMutexGuard::try_map(...)`. A
1047 /// method would interfere with methods of the same name on the contents of the locked data.
1048 ///
1049 /// # Examples
1050 ///
1051 /// ```
1052 /// use tokio::sync::{Mutex, OwnedMutexGuard};
1053 /// use std::sync::Arc;
1054 ///
1055 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1056 /// struct Foo(u32);
1057 ///
1058 /// # #[tokio::main]
1059 /// # async fn main() {
1060 /// let foo = Arc::new(Mutex::new(Foo(1)));
1061 ///
1062 /// {
1063 /// let mut mapped = OwnedMutexGuard::try_map(foo.clone().lock_owned().await, |f| Some(&mut f.0))
1064 /// .expect("should not fail");
1065 /// *mapped = 2;
1066 /// }
1067 ///
1068 /// assert_eq!(Foo(2), *foo.lock().await);
1069 /// # }
1070 /// ```
1071 ///
1072 /// [`OwnedMutexGuard`]: struct@OwnedMutexGuard
1073 /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard
1074 #[inline]
try_map<U, F>(mut this: Self, f: F) -> Result<OwnedMappedMutexGuard<T, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>,1075 pub fn try_map<U, F>(mut this: Self, f: F) -> Result<OwnedMappedMutexGuard<T, U>, Self>
1076 where
1077 F: FnOnce(&mut T) -> Option<&mut U>,
1078 {
1079 let data = match f(&mut *this) {
1080 Some(data) => data as *mut U,
1081 None => return Err(this),
1082 };
1083 let inner = this.skip_drop();
1084 Ok(OwnedMappedMutexGuard {
1085 data,
1086 lock: inner.lock,
1087 #[cfg(all(tokio_unstable, feature = "tracing"))]
1088 resource_span: inner.resource_span,
1089 })
1090 }
1091
1092 /// Returns a reference to the original `Arc<Mutex>`.
1093 ///
1094 /// ```
1095 /// use std::sync::Arc;
1096 /// use tokio::sync::{Mutex, OwnedMutexGuard};
1097 ///
1098 /// async fn unlock_and_relock(guard: OwnedMutexGuard<u32>) -> OwnedMutexGuard<u32> {
1099 /// println!("1. contains: {:?}", *guard);
1100 /// let mutex: Arc<Mutex<u32>> = OwnedMutexGuard::mutex(&guard).clone();
1101 /// drop(guard);
1102 /// let guard = mutex.lock_owned().await;
1103 /// println!("2. contains: {:?}", *guard);
1104 /// guard
1105 /// }
1106 /// #
1107 /// # #[tokio::main]
1108 /// # async fn main() {
1109 /// # let mutex = Arc::new(Mutex::new(0u32));
1110 /// # let guard = mutex.lock_owned().await;
1111 /// # unlock_and_relock(guard).await;
1112 /// # }
1113 /// ```
1114 #[inline]
mutex(this: &Self) -> &Arc<Mutex<T>>1115 pub fn mutex(this: &Self) -> &Arc<Mutex<T>> {
1116 &this.lock
1117 }
1118 }
1119
1120 impl<T: ?Sized> Drop for OwnedMutexGuard<T> {
drop(&mut self)1121 fn drop(&mut self) {
1122 self.lock.s.release(1);
1123
1124 #[cfg(all(tokio_unstable, feature = "tracing"))]
1125 self.resource_span.in_scope(|| {
1126 tracing::trace!(
1127 target: "runtime::resource::state_update",
1128 locked = false,
1129 );
1130 });
1131 }
1132 }
1133
1134 impl<T: ?Sized> Deref for OwnedMutexGuard<T> {
1135 type Target = T;
deref(&self) -> &Self::Target1136 fn deref(&self) -> &Self::Target {
1137 unsafe { &*self.lock.c.get() }
1138 }
1139 }
1140
1141 impl<T: ?Sized> DerefMut for OwnedMutexGuard<T> {
deref_mut(&mut self) -> &mut Self::Target1142 fn deref_mut(&mut self) -> &mut Self::Target {
1143 unsafe { &mut *self.lock.c.get() }
1144 }
1145 }
1146
1147 impl<T: ?Sized + fmt::Debug> fmt::Debug for OwnedMutexGuard<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1149 fmt::Debug::fmt(&**self, f)
1150 }
1151 }
1152
1153 impl<T: ?Sized + fmt::Display> fmt::Display for OwnedMutexGuard<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1155 fmt::Display::fmt(&**self, f)
1156 }
1157 }
1158
1159 // === impl MappedMutexGuard ===
1160
1161 impl<'a, T: ?Sized> MappedMutexGuard<'a, T> {
skip_drop(self) -> MappedMutexGuardInner<'a, T>1162 fn skip_drop(self) -> MappedMutexGuardInner<'a, T> {
1163 let me = mem::ManuallyDrop::new(self);
1164 MappedMutexGuardInner {
1165 s: me.s,
1166 data: me.data,
1167 #[cfg(all(tokio_unstable, feature = "tracing"))]
1168 resource_span: unsafe { std::ptr::read(&me.resource_span) },
1169 }
1170 }
1171
1172 /// Makes a new [`MappedMutexGuard`] for a component of the locked data.
1173 ///
1174 /// This operation cannot fail as the [`MappedMutexGuard`] passed in already locked the mutex.
1175 ///
1176 /// This is an associated function that needs to be used as `MappedMutexGuard::map(...)`. A
1177 /// method would interfere with methods of the same name on the contents of the locked data.
1178 ///
1179 /// [`MappedMutexGuard`]: struct@MappedMutexGuard
1180 #[inline]
map<U, F>(mut this: Self, f: F) -> MappedMutexGuard<'a, U> where F: FnOnce(&mut T) -> &mut U,1181 pub fn map<U, F>(mut this: Self, f: F) -> MappedMutexGuard<'a, U>
1182 where
1183 F: FnOnce(&mut T) -> &mut U,
1184 {
1185 let data = f(&mut *this) as *mut U;
1186 let inner = this.skip_drop();
1187 MappedMutexGuard {
1188 s: inner.s,
1189 data,
1190 marker: PhantomData,
1191 #[cfg(all(tokio_unstable, feature = "tracing"))]
1192 resource_span: inner.resource_span,
1193 }
1194 }
1195
1196 /// Attempts to make a new [`MappedMutexGuard`] for a component of the locked data. The
1197 /// original guard is returned if the closure returns `None`.
1198 ///
1199 /// This operation cannot fail as the [`MappedMutexGuard`] passed in already locked the mutex.
1200 ///
1201 /// This is an associated function that needs to be used as `MappedMutexGuard::try_map(...)`. A
1202 /// method would interfere with methods of the same name on the contents of the locked data.
1203 ///
1204 /// [`MappedMutexGuard`]: struct@MappedMutexGuard
1205 #[inline]
try_map<U, F>(mut this: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>,1206 pub fn try_map<U, F>(mut this: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
1207 where
1208 F: FnOnce(&mut T) -> Option<&mut U>,
1209 {
1210 let data = match f(&mut *this) {
1211 Some(data) => data as *mut U,
1212 None => return Err(this),
1213 };
1214 let inner = this.skip_drop();
1215 Ok(MappedMutexGuard {
1216 s: inner.s,
1217 data,
1218 marker: PhantomData,
1219 #[cfg(all(tokio_unstable, feature = "tracing"))]
1220 resource_span: inner.resource_span,
1221 })
1222 }
1223 }
1224
1225 impl<'a, T: ?Sized> Drop for MappedMutexGuard<'a, T> {
drop(&mut self)1226 fn drop(&mut self) {
1227 self.s.release(1);
1228
1229 #[cfg(all(tokio_unstable, feature = "tracing"))]
1230 self.resource_span.in_scope(|| {
1231 tracing::trace!(
1232 target: "runtime::resource::state_update",
1233 locked = false,
1234 );
1235 });
1236 }
1237 }
1238
1239 impl<'a, T: ?Sized> Deref for MappedMutexGuard<'a, T> {
1240 type Target = T;
deref(&self) -> &Self::Target1241 fn deref(&self) -> &Self::Target {
1242 unsafe { &*self.data }
1243 }
1244 }
1245
1246 impl<'a, T: ?Sized> DerefMut for MappedMutexGuard<'a, T> {
deref_mut(&mut self) -> &mut Self::Target1247 fn deref_mut(&mut self) -> &mut Self::Target {
1248 unsafe { &mut *self.data }
1249 }
1250 }
1251
1252 impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MappedMutexGuard<'a, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1254 fmt::Debug::fmt(&**self, f)
1255 }
1256 }
1257
1258 impl<'a, T: ?Sized + fmt::Display> fmt::Display for MappedMutexGuard<'a, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1260 fmt::Display::fmt(&**self, f)
1261 }
1262 }
1263
1264 // === impl OwnedMappedMutexGuard ===
1265
1266 impl<T: ?Sized, U: ?Sized> OwnedMappedMutexGuard<T, U> {
skip_drop(self) -> OwnedMappedMutexGuardInner<T, U>1267 fn skip_drop(self) -> OwnedMappedMutexGuardInner<T, U> {
1268 let me = mem::ManuallyDrop::new(self);
1269 // SAFETY: This duplicates the values in every field of the guard, then
1270 // forgets the originals, so in the end no value is duplicated.
1271 unsafe {
1272 OwnedMappedMutexGuardInner {
1273 data: me.data,
1274 lock: ptr::read(&me.lock),
1275 #[cfg(all(tokio_unstable, feature = "tracing"))]
1276 resource_span: ptr::read(&me.resource_span),
1277 }
1278 }
1279 }
1280
1281 /// Makes a new [`OwnedMappedMutexGuard`] for a component of the locked data.
1282 ///
1283 /// This operation cannot fail as the [`OwnedMappedMutexGuard`] passed in already locked the mutex.
1284 ///
1285 /// This is an associated function that needs to be used as `OwnedMappedMutexGuard::map(...)`. A method
1286 /// would interfere with methods of the same name on the contents of the locked data.
1287 ///
1288 /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard
1289 #[inline]
map<S, F>(mut this: Self, f: F) -> OwnedMappedMutexGuard<T, S> where F: FnOnce(&mut U) -> &mut S,1290 pub fn map<S, F>(mut this: Self, f: F) -> OwnedMappedMutexGuard<T, S>
1291 where
1292 F: FnOnce(&mut U) -> &mut S,
1293 {
1294 let data = f(&mut *this) as *mut S;
1295 let inner = this.skip_drop();
1296 OwnedMappedMutexGuard {
1297 data,
1298 lock: inner.lock,
1299 #[cfg(all(tokio_unstable, feature = "tracing"))]
1300 resource_span: inner.resource_span,
1301 }
1302 }
1303
1304 /// Attempts to make a new [`OwnedMappedMutexGuard`] for a component of the locked data. The
1305 /// original guard is returned if the closure returns `None`.
1306 ///
1307 /// This operation cannot fail as the [`OwnedMutexGuard`] passed in already locked the mutex.
1308 ///
1309 /// This is an associated function that needs to be used as `OwnedMutexGuard::try_map(...)`. A
1310 /// method would interfere with methods of the same name on the contents of the locked data.
1311 ///
1312 /// [`OwnedMutexGuard`]: struct@OwnedMutexGuard
1313 /// [`OwnedMappedMutexGuard`]: struct@OwnedMappedMutexGuard
1314 #[inline]
try_map<S, F>(mut this: Self, f: F) -> Result<OwnedMappedMutexGuard<T, S>, Self> where F: FnOnce(&mut U) -> Option<&mut S>,1315 pub fn try_map<S, F>(mut this: Self, f: F) -> Result<OwnedMappedMutexGuard<T, S>, Self>
1316 where
1317 F: FnOnce(&mut U) -> Option<&mut S>,
1318 {
1319 let data = match f(&mut *this) {
1320 Some(data) => data as *mut S,
1321 None => return Err(this),
1322 };
1323 let inner = this.skip_drop();
1324 Ok(OwnedMappedMutexGuard {
1325 data,
1326 lock: inner.lock,
1327 #[cfg(all(tokio_unstable, feature = "tracing"))]
1328 resource_span: inner.resource_span,
1329 })
1330 }
1331 }
1332
1333 impl<T: ?Sized, U: ?Sized> Drop for OwnedMappedMutexGuard<T, U> {
drop(&mut self)1334 fn drop(&mut self) {
1335 self.lock.s.release(1);
1336
1337 #[cfg(all(tokio_unstable, feature = "tracing"))]
1338 self.resource_span.in_scope(|| {
1339 tracing::trace!(
1340 target: "runtime::resource::state_update",
1341 locked = false,
1342 );
1343 });
1344 }
1345 }
1346
1347 impl<T: ?Sized, U: ?Sized> Deref for OwnedMappedMutexGuard<T, U> {
1348 type Target = U;
deref(&self) -> &Self::Target1349 fn deref(&self) -> &Self::Target {
1350 unsafe { &*self.data }
1351 }
1352 }
1353
1354 impl<T: ?Sized, U: ?Sized> DerefMut for OwnedMappedMutexGuard<T, U> {
deref_mut(&mut self) -> &mut Self::Target1355 fn deref_mut(&mut self) -> &mut Self::Target {
1356 unsafe { &mut *self.data }
1357 }
1358 }
1359
1360 impl<T: ?Sized, U: ?Sized + fmt::Debug> fmt::Debug for OwnedMappedMutexGuard<T, U> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1362 fmt::Debug::fmt(&**self, f)
1363 }
1364 }
1365
1366 impl<T: ?Sized, U: ?Sized + fmt::Display> fmt::Display for OwnedMappedMutexGuard<T, U> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1367 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1368 fmt::Display::fmt(&**self, f)
1369 }
1370 }
1371