mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 03:33:59 +00:00
Implmement MappedRwLock(Read|Write)Guard
.
This commit is contained in:
parent
9be1321676
commit
ea97c1f2dc
@ -3,6 +3,8 @@ mod tests;
|
|||||||
|
|
||||||
use crate::cell::UnsafeCell;
|
use crate::cell::UnsafeCell;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
|
use crate::marker::PhantomData;
|
||||||
|
use crate::mem::ManuallyDrop;
|
||||||
use crate::ops::{Deref, DerefMut};
|
use crate::ops::{Deref, DerefMut};
|
||||||
use crate::ptr::NonNull;
|
use crate::ptr::NonNull;
|
||||||
use crate::sync::{poison, LockResult, TryLockError, TryLockResult};
|
use crate::sync::{poison, LockResult, TryLockError, TryLockResult};
|
||||||
@ -105,7 +107,7 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
|
|||||||
#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockReadGuard")]
|
#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockReadGuard")]
|
||||||
pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
|
pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
|
||||||
// NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a
|
// NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a
|
||||||
// `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
|
// `RwLockReadGuard` argument doesn't hold immutability for its whole scope, only until it drops.
|
||||||
// `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull`
|
// `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull`
|
||||||
// is preferable over `const* T` to allow for niche optimization.
|
// is preferable over `const* T` to allow for niche optimization.
|
||||||
data: NonNull<T>,
|
data: NonNull<T>,
|
||||||
@ -144,6 +146,63 @@ impl<T: ?Sized> !Send for RwLockWriteGuard<'_, T> {}
|
|||||||
#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
|
#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
|
||||||
unsafe impl<T: ?Sized + Sync> Sync for RwLockWriteGuard<'_, T> {}
|
unsafe impl<T: ?Sized + Sync> Sync for RwLockWriteGuard<'_, T> {}
|
||||||
|
|
||||||
|
/// RAII structure used to release the shared read access of a lock when
|
||||||
|
/// dropped, which can point to a subfield of the protected data.
|
||||||
|
///
|
||||||
|
/// This structure is created by the [`map`] and [`try_map`] methods
|
||||||
|
/// on [`RwLockReadGuard`].
|
||||||
|
///
|
||||||
|
/// [`map`]: RwLockReadGuard::map
|
||||||
|
/// [`try_map`]: RwLockReadGuard::try_map
|
||||||
|
#[must_use = "if unused the RwLock will immediately unlock"]
|
||||||
|
#[must_not_suspend = "holding a MappedRwLockReadGuard across suspend \
|
||||||
|
points can cause deadlocks, delays, \
|
||||||
|
and cause Futures to not implement `Send`"]
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
#[clippy::has_significant_drop]
|
||||||
|
pub struct MappedRwLockReadGuard<'a, T: ?Sized + 'a> {
|
||||||
|
// NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a
|
||||||
|
// `MappedRwLockReadGuard` argument doesn't hold immutability for its whole scope, only until it drops.
|
||||||
|
// `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull`
|
||||||
|
// is preferable over `const* T` to allow for niche optimization.
|
||||||
|
data: NonNull<T>,
|
||||||
|
inner_lock: &'a sys::RwLock,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized> !Send for MappedRwLockReadGuard<'_, T> {}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockReadGuard<'_, T> {}
|
||||||
|
|
||||||
|
/// RAII structure used to release the exclusive write access of a lock when
|
||||||
|
/// dropped, which can point to a subfield of the protected data.
|
||||||
|
///
|
||||||
|
/// This structure is created by the [`map`] and [`try_map`] methods
|
||||||
|
/// on [`RwLockWriteGuard`].
|
||||||
|
///
|
||||||
|
/// [`map`]: RwLockWriteGuard::map
|
||||||
|
/// [`try_map`]: RwLockWriteGuard::try_map
|
||||||
|
#[must_use = "if unused the RwLock will immediately unlock"]
|
||||||
|
#[must_not_suspend = "holding a MappedRwLockWriteGuard across suspend \
|
||||||
|
points can cause deadlocks, delays, \
|
||||||
|
and cause Future's to not implement `Send`"]
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
#[clippy::has_significant_drop]
|
||||||
|
pub struct MappedRwLockWriteGuard<'a, T: ?Sized + 'a> {
|
||||||
|
data: NonNull<T>,
|
||||||
|
inner_lock: &'a sys::RwLock,
|
||||||
|
poison_flag: &'a poison::Flag,
|
||||||
|
poison: poison::Guard,
|
||||||
|
_variance: PhantomData<&'a mut T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized> !Send for MappedRwLockWriteGuard<'_, T> {}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockWriteGuard<'_, T> {}
|
||||||
|
|
||||||
impl<T> RwLock<T> {
|
impl<T> RwLock<T> {
|
||||||
/// Creates a new instance of an `RwLock<T>` which is unlocked.
|
/// Creates a new instance of an `RwLock<T>` which is unlocked.
|
||||||
///
|
///
|
||||||
@ -527,7 +586,10 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||||||
// SAFETY: if and only if `lock.inner.write()` (or `lock.inner.try_write()`) has been
|
// SAFETY: if and only if `lock.inner.write()` (or `lock.inner.try_write()`) has been
|
||||||
// successfully called from the same thread before instantiating this object.
|
// successfully called from the same thread before instantiating this object.
|
||||||
unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> {
|
unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> {
|
||||||
poison::map_result(lock.poison.guard(), |guard| RwLockWriteGuard { lock, poison: guard })
|
poison::map_result(lock.poison.guard(), |guard| RwLockWriteGuard {
|
||||||
|
lock,
|
||||||
|
poison: guard,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,12 +621,40 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
(**self).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
(**self).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
(**self).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
(**self).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
|
impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
// SAFETY: the conditions of `RwLockGuard::new` were satisfied when created.
|
// SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
|
||||||
unsafe { self.data.as_ref() }
|
unsafe { self.data.as_ref() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -587,6 +677,37 @@ impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
// SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
|
||||||
|
// was created, and have been upheld throughout `map` and/or `try_map`.
|
||||||
|
unsafe { self.data.as_ref() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
// SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
|
||||||
|
// was created, and have been upheld throughout `map` and/or `try_map`.
|
||||||
|
unsafe { self.data.as_ref() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
// SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
|
||||||
|
// was created, and have been upheld throughout `map` and/or `try_map`.
|
||||||
|
unsafe { self.data.as_mut() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
|
impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
@ -607,3 +728,234 @@ impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
|
||||||
|
// was created, and have been upheld throughout `map` and/or `try_map`.
|
||||||
|
unsafe {
|
||||||
|
self.inner_lock.read_unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.poison_flag.done(&self.poison);
|
||||||
|
// SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
|
||||||
|
// was created, and have been upheld throughout `map` and/or `try_map`.
|
||||||
|
unsafe {
|
||||||
|
self.inner_lock.write_unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: ?Sized> RwLockReadGuard<'a, T> {
|
||||||
|
/// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data, e.g.
|
||||||
|
/// an enum variant.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for reading, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `RwLockReadGuard::map(...)`. A method would interfere with methods of
|
||||||
|
/// the same name on the contents of the `RwLockReadGuard` used through
|
||||||
|
/// `Deref`.
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U>
|
||||||
|
where
|
||||||
|
F: FnOnce(&T) -> &U,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let orig = ManuallyDrop::new(orig);
|
||||||
|
let value = NonNull::from(f(&*orig));
|
||||||
|
MappedRwLockReadGuard { data: value, inner_lock: &orig.inner_lock }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The
|
||||||
|
/// original guard is returned as an `Err(...)` if the closure returns
|
||||||
|
/// `None`.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for reading, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `RwLockReadGuard::try_map(...)`. A method would interfere with methods
|
||||||
|
/// of the same name on the contents of the `RwLockReadGuard` used through
|
||||||
|
/// `Deref`.
|
||||||
|
#[doc(alias = "filter_map")]
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'a, U>, Self>
|
||||||
|
where
|
||||||
|
F: FnOnce(&T) -> Option<&U>,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let orig = ManuallyDrop::new(orig);
|
||||||
|
match f(&*orig).map(NonNull::from) {
|
||||||
|
Some(value) => Ok(MappedRwLockReadGuard { data: value, inner_lock: &orig.inner_lock }),
|
||||||
|
None => Err(ManuallyDrop::into_inner(orig)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: ?Sized> MappedRwLockReadGuard<'a, T> {
|
||||||
|
/// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data,
|
||||||
|
/// e.g. an enum variant.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for reading, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `MappedRwLockReadGuard::map(...)`. A method would interfere with
|
||||||
|
/// methods of the same name on the contents of the `MappedRwLockReadGuard`
|
||||||
|
/// used through `Deref`.
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U>
|
||||||
|
where
|
||||||
|
F: FnOnce(&T) -> &U,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let orig = ManuallyDrop::new(orig);
|
||||||
|
let value = NonNull::from(f(&*orig));
|
||||||
|
MappedRwLockReadGuard { data: value, inner_lock: &orig.inner_lock }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data.
|
||||||
|
/// The original guard is returned as an `Err(...)` if the closure returns
|
||||||
|
/// `None`.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for reading, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `MappedRwLockReadGuard::try_map(...)`. A method would interfere with
|
||||||
|
/// methods of the same name on the contents of the `MappedRwLockReadGuard`
|
||||||
|
/// used through `Deref`.
|
||||||
|
#[doc(alias = "filter_map")]
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'a, U>, Self>
|
||||||
|
where
|
||||||
|
F: FnOnce(&T) -> Option<&U>,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let orig = ManuallyDrop::new(orig);
|
||||||
|
match f(&*orig).map(NonNull::from) {
|
||||||
|
Some(value) => Ok(MappedRwLockReadGuard { data: value, inner_lock: &orig.inner_lock }),
|
||||||
|
None => Err(ManuallyDrop::into_inner(orig)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
|
||||||
|
/// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g.
|
||||||
|
/// an enum variant.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for writing, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `RwLockWriteGuard::map(...)`. A method would interfere with methods of
|
||||||
|
/// the same name on the contents of the `RwLockWriteGuard` used through
|
||||||
|
/// `Deref`.
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut T) -> &mut U,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let mut orig = ManuallyDrop::new(orig);
|
||||||
|
let value = NonNull::from(f(&mut *orig));
|
||||||
|
MappedRwLockWriteGuard {
|
||||||
|
data: value,
|
||||||
|
inner_lock: &orig.lock.inner,
|
||||||
|
poison_flag: &orig.lock.poison,
|
||||||
|
poison: orig.poison.clone(),
|
||||||
|
_variance: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The
|
||||||
|
/// original guard is returned as an `Err(...)` if the closure returns
|
||||||
|
/// `None`.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for writing, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `RwLockWriteGuard::try_map(...)`. A method would interfere with methods
|
||||||
|
/// of the same name on the contents of the `RwLockWriteGuard` used through
|
||||||
|
/// `Deref`.
|
||||||
|
#[doc(alias = "filter_map")]
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, U>, Self>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut T) -> Option<&mut U>,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let mut orig = ManuallyDrop::new(orig);
|
||||||
|
match f(&mut *orig).map(NonNull::from) {
|
||||||
|
Some(value) => Ok(MappedRwLockWriteGuard {
|
||||||
|
data: value,
|
||||||
|
inner_lock: &orig.lock.inner,
|
||||||
|
poison_flag: &orig.lock.poison,
|
||||||
|
poison: orig.poison.clone(),
|
||||||
|
_variance: PhantomData,
|
||||||
|
}),
|
||||||
|
None => Err(ManuallyDrop::into_inner(orig)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: ?Sized> MappedRwLockWriteGuard<'a, T> {
|
||||||
|
/// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data,
|
||||||
|
/// e.g. an enum variant.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for writing, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `MappedRwLockWriteGuard::map(...)`. A method would interfere with
|
||||||
|
/// methods of the same name on the contents of the `MappedRwLockWriteGuard`
|
||||||
|
/// used through `Deref`.
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut T) -> &mut U,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let mut orig = ManuallyDrop::new(orig);
|
||||||
|
let value = NonNull::from(f(&mut *orig));
|
||||||
|
MappedRwLockWriteGuard {
|
||||||
|
data: value,
|
||||||
|
inner_lock: orig.inner_lock,
|
||||||
|
poison_flag: orig.poison_flag,
|
||||||
|
poison: orig.poison.clone(),
|
||||||
|
_variance: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data.
|
||||||
|
/// The original guard is returned as an `Err(...)` if the closure returns
|
||||||
|
/// `None`.
|
||||||
|
///
|
||||||
|
/// The `RwLock` is already locked for writing, so this cannot fail.
|
||||||
|
///
|
||||||
|
/// This is an associated function that needs to be used as
|
||||||
|
/// `MappedRwLockWriteGuard::try_map(...)`. A method would interfere with
|
||||||
|
/// methods of the same name on the contents of the `MappedRwLockWriteGuard`
|
||||||
|
/// used through `Deref`.
|
||||||
|
#[doc(alias = "filter_map")]
|
||||||
|
#[unstable(feature = "mapped_lock_guards", issue = "none")]
|
||||||
|
pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, U>, Self>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut T) -> Option<&mut U>,
|
||||||
|
U: ?Sized,
|
||||||
|
{
|
||||||
|
let mut orig = ManuallyDrop::new(orig);
|
||||||
|
match f(&mut *orig).map(NonNull::from) {
|
||||||
|
Some(value) => Ok(MappedRwLockWriteGuard {
|
||||||
|
data: value,
|
||||||
|
inner_lock: orig.inner_lock,
|
||||||
|
poison_flag: orig.poison_flag,
|
||||||
|
poison: orig.poison.clone(),
|
||||||
|
_variance: PhantomData,
|
||||||
|
}),
|
||||||
|
None => Err(ManuallyDrop::into_inner(orig)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user