use std::cell::UnsafeCell; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::pin::Pin; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex as StdMutex}; use std::{fmt, mem};
use slab::Slab;
use futures_core::future::{FusedFuture, Future}; use futures_core::task::{Context, Poll, Waker};
/// A futures-aware mutex. /// /// # Fairness /// /// This mutex provides no fairness guarantees. Tasks may not acquire the mutex /// in the order that they requested the lock, and it's possible for a single task /// which repeatedly takes the lock to starve other tasks, which may be left waiting /// indefinitely. pubstruct Mutex<T: ?Sized> {
state: AtomicUsize,
waiters: StdMutex<Slab<Waiter>>,
value: UnsafeCell<T>,
}
/// Consumes this mutex, returning the underlying data. /// /// # Examples /// /// ``` /// use futures::lock::Mutex; /// /// let mutex = Mutex::new(0); /// assert_eq!(mutex.into_inner(), 0); /// ``` pubfn into_inner(self) -> T { self.value.into_inner()
}
}
impl<T: ?Sized> Mutex<T> { /// Attempt to acquire the lock immediately. /// /// If the lock is currently held, this will return `None`. pubfn try_lock(&self) -> Option<MutexGuard<'_, T>> { let old_state = self.state.fetch_or(IS_LOCKED, Ordering::Acquire); if (old_state & IS_LOCKED) == 0 {
Some(MutexGuard { mutex: self })
} else {
None
}
}
/// Attempt to acquire the lock immediately. /// /// If the lock is currently held, this will return `None`. pubfn try_lock_owned(self: &Arc<Self>) -> Option<OwnedMutexGuard<T>> { let old_state = self.state.fetch_or(IS_LOCKED, Ordering::Acquire); if (old_state & IS_LOCKED) == 0 {
Some(OwnedMutexGuard { mutex: self.clone() })
} else {
None
}
}
/// Acquire the lock asynchronously. /// /// This method returns a future that will resolve once the lock has been /// successfully acquired. pubfn lock(&self) -> MutexLockFuture<'_, T> {
MutexLockFuture { mutex: Some(self), wait_key: WAIT_KEY_NONE }
}
/// Acquire the lock asynchronously. /// /// This method returns a future that will resolve once the lock has been /// successfully acquired. pubfn lock_owned(self: Arc<Self>) -> OwnedMutexLockFuture<T> {
OwnedMutexLockFuture { mutex: Some(self), wait_key: WAIT_KEY_NONE }
}
/// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `Mutex` mutably, no actual locking needs to /// take place -- the mutable borrow statically guarantees no locks exist. /// /// # Examples /// /// ``` /// # futures::executor::block_on(async { /// use futures::lock::Mutex; /// /// let mut mutex = Mutex::new(0); /// *mutex.get_mut() = 10; /// assert_eq!(*mutex.lock().await, 10); /// # }); /// ``` pubfn get_mut(&mutself) -> &mut T { // We know statically that there are no other references to `self`, so // there's no need to lock the inner mutex. unsafe { &mut *self.value.get() }
}
fn remove_waker(&self, wait_key: usize, wake_another: bool) { if wait_key != WAIT_KEY_NONE { letmut waiters = self.waiters.lock().unwrap(); match waiters.remove(wait_key) {
Waiter::Waiting(_) => {}
Waiter::Woken => { // We were awoken, but then dropped before we could // wake up to acquire the lock. Wake up another // waiter. if wake_another { iflet Some((_i, waiter)) = waiters.iter_mut().next() {
waiter.wake();
}
}
}
} if waiters.is_empty() { self.state.fetch_and(!HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
}
}
}
// Unlocks the mutex. Called by MutexGuard and MappedMutexGuard when they are // dropped. fn unlock(&self) { let old_state = self.state.fetch_and(!IS_LOCKED, Ordering::AcqRel); if (old_state & HAS_WAITERS) != 0 { letmut waiters = self.waiters.lock().unwrap(); iflet Some((_i, waiter)) = waiters.iter_mut().next() {
waiter.wake();
}
}
}
}
// Sentinel for when no slot in the `Slab` has been dedicated to this object. const WAIT_KEY_NONE: usize = usize::MAX;
/// A future which resolves when the target mutex has been successfully acquired, owned version. pubstruct OwnedMutexLockFuture<T: ?Sized> { // `None` indicates that the mutex was successfully acquired.
mutex: Option<Arc<Mutex<T>>>,
wait_key: usize,
}
{ letmut waiters = mutex.waiters.lock().unwrap(); if this.wait_key == WAIT_KEY_NONE {
this.wait_key = waiters.insert(Waiter::Waiting(cx.waker().clone())); if waiters.len() == 1 {
mutex.state.fetch_or(HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
}
} else {
waiters[this.wait_key].register(cx.waker());
}
}
// Ensure that we haven't raced `MutexGuard::drop`'s unlock path by // attempting to acquire the lock again. iflet Some(lock) = mutex.try_lock_owned() {
mutex.remove_waker(this.wait_key, false);
this.mutex = None; return Poll::Ready(lock);
}
Poll::Pending
}
}
impl<T: ?Sized> Drop for OwnedMutexLockFuture<T> { fn drop(&mutself) { iflet Some(mutex) = self.mutex.as_ref() { // This future was dropped before it acquired the mutex. // // Remove ourselves from the map, waking up another waiter if we // had been awoken to acquire the lock.
mutex.remove_waker(self.wait_key, true);
}
}
}
/// An RAII guard returned by the `lock_owned` and `try_lock_owned` methods. /// When this structure is dropped (falls out of scope), the lock will be /// unlocked. pubstruct OwnedMutexGuard<T: ?Sized> {
mutex: Arc<Mutex<T>>,
}
impl<T: ?Sized> DerefMut for OwnedMutexGuard<T> { fn deref_mut(&mutself) -> &mut T { unsafe { &mut *self.mutex.value.get() }
}
}
/// A future which resolves when the target mutex has been successfully acquired. pubstruct MutexLockFuture<'a, T: ?Sized> { // `None` indicates that the mutex was successfully acquired.
mutex: Option<&'a Mutex<T>>,
wait_key: usize,
}
// Ensure that we haven't raced `MutexGuard::drop`'s unlock path by // attempting to acquire the lock again. iflet Some(lock) = mutex.try_lock() {
mutex.remove_waker(self.wait_key, false); self.mutex = None; return Poll::Ready(lock);
}
Poll::Pending
}
}
impl<T: ?Sized> Drop for MutexLockFuture<'_, T> { fn drop(&mutself) { iflet Some(mutex) = self.mutex { // This future was dropped before it acquired the mutex. // // Remove ourselves from the map, waking up another waiter if we // had been awoken to acquire the lock.
mutex.remove_waker(self.wait_key, true);
}
}
}
/// An RAII guard returned by the `lock` and `try_lock` methods. /// When this structure is dropped (falls out of scope), the lock will be /// unlocked. pubstruct MutexGuard<'a, T: ?Sized> {
mutex: &'a Mutex<T>,
}
impl<'a, T: ?Sized> MutexGuard<'a, T> { /// Returns a locked view over a portion of the locked data. /// /// # Example /// /// ``` /// # futures::executor::block_on(async { /// use futures::lock::{Mutex, MutexGuard}; /// /// let data = Mutex::new(Some("value".to_string())); /// { /// let locked_str = MutexGuard::map(data.lock().await, |opt| opt.as_mut().unwrap()); /// assert_eq!(&*locked_str, "value"); /// } /// # }); /// ``` #[inline] pubfn map<U: ?Sized, F>(this: Self, f: F) -> MappedMutexGuard<'a, T, U> where
F: FnOnce(&mut T) -> &mut U,
{ let mutex = this.mutex; let value = f(unsafe { &mut *this.mutex.value.get() }); // Don't run the `drop` method for MutexGuard. The ownership of the underlying // locked state is being moved to the returned MappedMutexGuard.
mem::forget(this);
MappedMutexGuard { mutex, value, _marker: PhantomData }
}
}
impl<T: ?Sized> DerefMut for MutexGuard<'_, T> { fn deref_mut(&mutself) -> &mut T { unsafe { &mut *self.mutex.value.get() }
}
}
/// An RAII guard returned by the `MutexGuard::map` and `MappedMutexGuard::map` methods. /// When this structure is dropped (falls out of scope), the lock will be unlocked. pubstruct MappedMutexGuard<'a, T: ?Sized, U: ?Sized> {
mutex: &'a Mutex<T>,
value: *mut U,
_marker: PhantomData<&'a mut U>,
}
impl<'a, T: ?Sized, U: ?Sized> MappedMutexGuard<'a, T, U> { /// Returns a locked view over a portion of the locked data. /// /// # Example /// /// ``` /// # futures::executor::block_on(async { /// use futures::lock::{MappedMutexGuard, Mutex, MutexGuard}; /// /// let data = Mutex::new(Some("value".to_string())); /// { /// let locked_str = MutexGuard::map(data.lock().await, |opt| opt.as_mut().unwrap()); /// let locked_char = MappedMutexGuard::map(locked_str, |s| s.get_mut(0..1).unwrap()); /// assert_eq!(&*locked_char, "v"); /// } /// # }); /// ``` #[inline] pubfn map<V: ?Sized, F>(this: Self, f: F) -> MappedMutexGuard<'a, T, V> where
F: FnOnce(&mut U) -> &mut V,
{ let mutex = this.mutex; let value = f(unsafe { &mut *this.value }); // Don't run the `drop` method for MappedMutexGuard. The ownership of the underlying // locked state is being moved to the returned MappedMutexGuard.
mem::forget(this);
MappedMutexGuard { mutex, value, _marker: PhantomData }
}
}
// Mutexes can be moved freely between threads and acquired on any thread so long // as the inner value can be safely sent between threads. unsafeimpl<T: ?Sized + Send> Send for Mutex<T> {} unsafeimpl<T: ?Sized + Send> Sync for Mutex<T> {}
// It's safe to switch which thread the acquire is being attempted on so long as // `T` can be accessed on that thread. unsafeimpl<T: ?Sized + Send> Send for MutexLockFuture<'_, T> {}
// doesn't have any interesting `&self` methods (only Debug) unsafeimpl<T: ?Sized> Sync for MutexLockFuture<'_, T> {}
// It's safe to switch which thread the acquire is being attempted on so long as // `T` can be accessed on that thread. unsafeimpl<T: ?Sized + Send> Send for OwnedMutexLockFuture<T> {}
// doesn't have any interesting `&self` methods (only Debug) unsafeimpl<T: ?Sized> Sync for OwnedMutexLockFuture<T> {}
// Safe to send since we don't track any thread-specific details-- the inner // lock is essentially spinlock-equivalent (attempt to flip an atomic bool) unsafeimpl<T: ?Sized + Send> Send for MutexGuard<'_, T> {} unsafeimpl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {}
unsafeimpl<T: ?Sized + Send> Send for OwnedMutexGuard<T> {} unsafeimpl<T: ?Sized + Sync> Sync for OwnedMutexGuard<T> {}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.