Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Mutex::blocking_lock_owned #5130

Merged
merged 1 commit into from Oct 29, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
56 changes: 56 additions & 0 deletions tokio/src/sync/mutex.rs
Expand Up @@ -418,6 +418,62 @@ impl<T: ?Sized> Mutex<T> {
crate::future::block_on(self.lock())
}

/// Blockingly locks this `Mutex`. When the lock has been acquired, function returns an
/// [`OwnedMutexGuard`].
///
/// This method is identical to [`Mutex::blocking_lock`], except that the returned
/// guard references the `Mutex` with an [`Arc`] rather than by borrowing
/// it. Therefore, the `Mutex` must be wrapped in an `Arc` to call this
/// method, and the guard will live for the `'static` lifetime, as it keeps
/// the `Mutex` alive by holding an `Arc`.
///
/// # Panics
///
/// This function panics if called within an asynchronous execution context.
///
/// - If you find yourself in an asynchronous execution context and needing
/// to call some (synchronous) function which performs one of these
/// `blocking_` operations, then consider wrapping that call inside
/// [`spawn_blocking()`][crate::runtime::Handle::spawn_blocking]
/// (or [`block_in_place()`][crate::task::block_in_place]).
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use tokio::sync::Mutex;
///
/// #[tokio::main]
/// async fn main() {
/// let mutex = Arc::new(Mutex::new(1));
/// let lock = mutex.lock().await;
///
/// let mutex1 = Arc::clone(&mutex);
/// let blocking_task = tokio::task::spawn_blocking(move || {
/// // This shall block until the `lock` is released.
/// let mut n = mutex1.blocking_lock_owned();
/// *n = 2;
/// });
///
/// assert_eq!(*lock, 1);
/// // Release the lock.
/// drop(lock);
///
/// // Await the completion of the blocking task.
/// blocking_task.await.unwrap();
///
/// // Assert uncontended.
/// let n = mutex.try_lock().unwrap();
/// assert_eq!(*n, 2);
/// }
///
/// ```
#[track_caller]
#[cfg(feature = "sync")]
pub fn blocking_lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T> {
crate::future::block_on(self.lock_owned())
}

/// Locks this mutex, causing the current task to yield until the lock has
/// been acquired. When the lock has been acquired, this returns an
/// [`OwnedMutexGuard`].
Expand Down