Change MutexGuard and RwLockWriteGuard to store &mut T not &UnsafeCell<T>
This centralizes the unsafety of converting from UnsafeCell<T> to &mut T.
This commit is contained in:
@@ -172,7 +172,7 @@ pub struct MutexGuard<'a, T: ?Sized + 'a> {
|
|||||||
// funny underscores due to how Deref/DerefMut currently work (they
|
// funny underscores due to how Deref/DerefMut currently work (they
|
||||||
// disregard field privacy).
|
// disregard field privacy).
|
||||||
__lock: &'a StaticMutex,
|
__lock: &'a StaticMutex,
|
||||||
__data: &'a UnsafeCell<T>,
|
__data: &'a mut T,
|
||||||
__poison: poison::Guard,
|
__poison: poison::Guard,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ impl<T: ?Sized> Mutex<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn lock(&self) -> LockResult<MutexGuard<T>> {
|
pub fn lock(&self) -> LockResult<MutexGuard<T>> {
|
||||||
unsafe { self.inner.lock.lock() }
|
unsafe { self.inner.lock.lock() }
|
||||||
MutexGuard::new(&*self.inner, &self.data)
|
unsafe { MutexGuard::new(&*self.inner, &self.data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to acquire this lock.
|
/// Attempts to acquire this lock.
|
||||||
@@ -231,7 +231,7 @@ impl<T: ?Sized> Mutex<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
|
pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
|
||||||
if unsafe { self.inner.lock.try_lock() } {
|
if unsafe { self.inner.lock.try_lock() } {
|
||||||
Ok(try!(MutexGuard::new(&*self.inner, &self.data)))
|
Ok(try!(unsafe { MutexGuard::new(&*self.inner, &self.data) }))
|
||||||
} else {
|
} else {
|
||||||
Err(TryLockError::WouldBlock)
|
Err(TryLockError::WouldBlock)
|
||||||
}
|
}
|
||||||
@@ -339,14 +339,14 @@ impl StaticMutex {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
|
pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
|
||||||
unsafe { self.lock.lock() }
|
unsafe { self.lock.lock() }
|
||||||
MutexGuard::new(self, &DUMMY.0)
|
unsafe { MutexGuard::new(self, &DUMMY.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to grab this lock, see `Mutex::try_lock`
|
/// Attempts to grab this lock, see `Mutex::try_lock`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
|
pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
|
||||||
if unsafe { self.lock.try_lock() } {
|
if unsafe { self.lock.try_lock() } {
|
||||||
Ok(try!(MutexGuard::new(self, &DUMMY.0)))
|
Ok(try!(unsafe { MutexGuard::new(self, &DUMMY.0) }))
|
||||||
} else {
|
} else {
|
||||||
Err(TryLockError::WouldBlock)
|
Err(TryLockError::WouldBlock)
|
||||||
}
|
}
|
||||||
@@ -369,12 +369,12 @@ impl StaticMutex {
|
|||||||
|
|
||||||
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
|
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
|
||||||
|
|
||||||
fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
|
unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
|
||||||
-> LockResult<MutexGuard<'mutex, T>> {
|
-> LockResult<MutexGuard<'mutex, T>> {
|
||||||
poison::map_result(lock.poison.borrow(), |guard| {
|
poison::map_result(lock.poison.borrow(), |guard| {
|
||||||
MutexGuard {
|
MutexGuard {
|
||||||
__lock: lock,
|
__lock: lock,
|
||||||
__data: data,
|
__data: &mut *data.get(),
|
||||||
__poison: guard,
|
__poison: guard,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -385,7 +385,10 @@ impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
|
|||||||
/// Applies the supplied closure to the data, returning a new lock
|
/// Applies the supplied closure to the data, returning a new lock
|
||||||
/// guard referencing the borrow returned by the closure.
|
/// guard referencing the borrow returned by the closure.
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # #![feature(guard_map)]
|
||||||
/// # use std::sync::{Mutex, MutexGuard};
|
/// # use std::sync::{Mutex, MutexGuard};
|
||||||
/// let x = Mutex::new(vec![1, 2]);
|
/// let x = Mutex::new(vec![1, 2]);
|
||||||
///
|
///
|
||||||
@@ -401,13 +404,15 @@ impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
|
|||||||
issue = "0")]
|
issue = "0")]
|
||||||
pub fn map<U: ?Sized, F>(this: Self, cb: F) -> MutexGuard<'mutex, U>
|
pub fn map<U: ?Sized, F>(this: Self, cb: F) -> MutexGuard<'mutex, U>
|
||||||
where F: FnOnce(&'mutex mut T) -> &'mutex mut U {
|
where F: FnOnce(&'mutex mut T) -> &'mutex mut U {
|
||||||
let new_data = unsafe {
|
// Compute the new data while still owning the original lock
|
||||||
let data = cb(&mut *this.__data.get());
|
// in order to correctly poison if the callback panics.
|
||||||
mem::transmute::<&'mutex mut U, &'mutex UnsafeCell<U>>(data)
|
let data = unsafe { ptr::read(&this.__data) };
|
||||||
};
|
let new_data = cb(data);
|
||||||
|
|
||||||
let lock = unsafe { ptr::read(&this.__lock) };
|
// We don't want to unlock the lock by running the destructor of the
|
||||||
|
// original lock, so just read the fields we need and forget it.
|
||||||
let poison = unsafe { ptr::read(&this.__poison) };
|
let poison = unsafe { ptr::read(&this.__poison) };
|
||||||
|
let lock = unsafe { ptr::read(&this.__lock) };
|
||||||
mem::forget(this);
|
mem::forget(this);
|
||||||
|
|
||||||
MutexGuard {
|
MutexGuard {
|
||||||
@@ -422,16 +427,12 @@ impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
|
|||||||
impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
|
impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {self.__data }
|
||||||
unsafe { &*self.__data.get() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
|
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
|
||||||
fn deref_mut(&mut self) -> &mut T {
|
fn deref_mut(&mut self) -> &mut T { self.__data }
|
||||||
unsafe { &mut *self.__data.get() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
|
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
|
||||||
__lock: &'a StaticRwLock,
|
__lock: &'a StaticRwLock,
|
||||||
__data: &'a UnsafeCell<T>,
|
__data: &'a mut T,
|
||||||
__poison: poison::Guard,
|
__poison: poison::Guard,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ impl<T: ?Sized> RwLock<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
|
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
|
||||||
unsafe { self.inner.lock.read() }
|
unsafe { self.inner.lock.read() }
|
||||||
RwLockReadGuard::new(&*self.inner, &self.data)
|
unsafe { RwLockReadGuard::new(&*self.inner, &self.data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to acquire this rwlock with shared read access.
|
/// Attempts to acquire this rwlock with shared read access.
|
||||||
@@ -202,7 +202,7 @@ impl<T: ?Sized> RwLock<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
|
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
|
||||||
if unsafe { self.inner.lock.try_read() } {
|
if unsafe { self.inner.lock.try_read() } {
|
||||||
Ok(try!(RwLockReadGuard::new(&*self.inner, &self.data)))
|
Ok(try!(unsafe { RwLockReadGuard::new(&*self.inner, &self.data) }))
|
||||||
} else {
|
} else {
|
||||||
Err(TryLockError::WouldBlock)
|
Err(TryLockError::WouldBlock)
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ impl<T: ?Sized> RwLock<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
|
pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
|
||||||
unsafe { self.inner.lock.write() }
|
unsafe { self.inner.lock.write() }
|
||||||
RwLockWriteGuard::new(&*self.inner, &self.data)
|
unsafe { RwLockWriteGuard::new(&*self.inner, &self.data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to lock this rwlock with exclusive write access.
|
/// Attempts to lock this rwlock with exclusive write access.
|
||||||
@@ -250,7 +250,7 @@ impl<T: ?Sized> RwLock<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
|
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
|
||||||
if unsafe { self.inner.lock.try_write() } {
|
if unsafe { self.inner.lock.try_write() } {
|
||||||
Ok(try!(RwLockWriteGuard::new(&*self.inner, &self.data)))
|
Ok(try!(unsafe { RwLockWriteGuard::new(&*self.inner, &self.data) }))
|
||||||
} else {
|
} else {
|
||||||
Err(TryLockError::WouldBlock)
|
Err(TryLockError::WouldBlock)
|
||||||
}
|
}
|
||||||
@@ -361,7 +361,7 @@ impl StaticRwLock {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> {
|
pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> {
|
||||||
unsafe { self.lock.read() }
|
unsafe { self.lock.read() }
|
||||||
RwLockReadGuard::new(self, &DUMMY.0)
|
unsafe { RwLockReadGuard::new(self, &DUMMY.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to acquire this lock with shared read access.
|
/// Attempts to acquire this lock with shared read access.
|
||||||
@@ -371,7 +371,7 @@ impl StaticRwLock {
|
|||||||
pub fn try_read(&'static self)
|
pub fn try_read(&'static self)
|
||||||
-> TryLockResult<RwLockReadGuard<'static, ()>> {
|
-> TryLockResult<RwLockReadGuard<'static, ()>> {
|
||||||
if unsafe { self.lock.try_read() } {
|
if unsafe { self.lock.try_read() } {
|
||||||
Ok(try!(RwLockReadGuard::new(self, &DUMMY.0)))
|
unsafe { Ok(try!(RwLockReadGuard::new(self, &DUMMY.0))) }
|
||||||
} else {
|
} else {
|
||||||
Err(TryLockError::WouldBlock)
|
Err(TryLockError::WouldBlock)
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,7 @@ impl StaticRwLock {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> {
|
pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> {
|
||||||
unsafe { self.lock.write() }
|
unsafe { self.lock.write() }
|
||||||
RwLockWriteGuard::new(self, &DUMMY.0)
|
unsafe { RwLockWriteGuard::new(self, &DUMMY.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to lock this rwlock with exclusive write access.
|
/// Attempts to lock this rwlock with exclusive write access.
|
||||||
@@ -394,7 +394,7 @@ impl StaticRwLock {
|
|||||||
pub fn try_write(&'static self)
|
pub fn try_write(&'static self)
|
||||||
-> TryLockResult<RwLockWriteGuard<'static, ()>> {
|
-> TryLockResult<RwLockWriteGuard<'static, ()>> {
|
||||||
if unsafe { self.lock.try_write() } {
|
if unsafe { self.lock.try_write() } {
|
||||||
Ok(try!(RwLockWriteGuard::new(self, &DUMMY.0)))
|
Ok(unsafe { try!(RwLockWriteGuard::new(self, &DUMMY.0)) })
|
||||||
} else {
|
} else {
|
||||||
Err(TryLockError::WouldBlock)
|
Err(TryLockError::WouldBlock)
|
||||||
}
|
}
|
||||||
@@ -412,12 +412,12 @@ impl StaticRwLock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
|
impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
|
||||||
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
||||||
-> LockResult<RwLockReadGuard<'rwlock, T>> {
|
-> LockResult<RwLockReadGuard<'rwlock, T>> {
|
||||||
poison::map_result(lock.poison.borrow(), |_| {
|
poison::map_result(lock.poison.borrow(), |_| {
|
||||||
RwLockReadGuard {
|
RwLockReadGuard {
|
||||||
__lock: lock,
|
__lock: lock,
|
||||||
__data: unsafe { &*data.get() },
|
__data: &*data.get(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -427,7 +427,10 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
|
|||||||
/// Applies the supplied closure to the data, returning a new lock
|
/// Applies the supplied closure to the data, returning a new lock
|
||||||
/// guard referencing the borrow returned by the closure.
|
/// guard referencing the borrow returned by the closure.
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # #![feature(guard_map)]
|
||||||
/// # use std::sync::{RwLockReadGuard, RwLock};
|
/// # use std::sync::{RwLockReadGuard, RwLock};
|
||||||
/// let x = RwLock::new(vec![1, 2]);
|
/// let x = RwLock::new(vec![1, 2]);
|
||||||
///
|
///
|
||||||
@@ -451,12 +454,12 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
||||||
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
||||||
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
|
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
|
||||||
poison::map_result(lock.poison.borrow(), |guard| {
|
poison::map_result(lock.poison.borrow(), |guard| {
|
||||||
RwLockWriteGuard {
|
RwLockWriteGuard {
|
||||||
__lock: lock,
|
__lock: lock,
|
||||||
__data: data,
|
__data: &mut *data.get(),
|
||||||
__poison: guard,
|
__poison: guard,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -467,7 +470,10 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||||||
/// Applies the supplied closure to the data, returning a new lock
|
/// Applies the supplied closure to the data, returning a new lock
|
||||||
/// guard referencing the borrow returned by the closure.
|
/// guard referencing the borrow returned by the closure.
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # #![feature(guard_map)]
|
||||||
/// # use std::sync::{RwLockWriteGuard, RwLock};
|
/// # use std::sync::{RwLockWriteGuard, RwLock};
|
||||||
/// let x = RwLock::new(vec![1, 2]);
|
/// let x = RwLock::new(vec![1, 2]);
|
||||||
///
|
///
|
||||||
@@ -485,11 +491,13 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||||||
issue = "0")]
|
issue = "0")]
|
||||||
pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockWriteGuard<'rwlock, U>
|
pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockWriteGuard<'rwlock, U>
|
||||||
where F: FnOnce(&'rwlock mut T) -> &'rwlock mut U {
|
where F: FnOnce(&'rwlock mut T) -> &'rwlock mut U {
|
||||||
let new_data = unsafe {
|
// Compute the new data while still owning the original lock
|
||||||
let data: &'rwlock mut T = &mut *this.__data.get();
|
// in order to correctly poison if the callback panics.
|
||||||
mem::transmute::<&'rwlock mut U, &'rwlock UnsafeCell<U>>(cb(data))
|
let data = unsafe { ptr::read(&this.__data) };
|
||||||
};
|
let new_data = cb(data);
|
||||||
|
|
||||||
|
// We don't want to unlock the lock by running the destructor of the
|
||||||
|
// original lock, so just read the fields we need and forget it.
|
||||||
let poison = unsafe { ptr::read(&this.__poison) };
|
let poison = unsafe { ptr::read(&this.__poison) };
|
||||||
let lock = unsafe { ptr::read(&this.__lock) };
|
let lock = unsafe { ptr::read(&this.__lock) };
|
||||||
mem::forget(this);
|
mem::forget(this);
|
||||||
@@ -513,13 +521,12 @@ impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> {
|
|||||||
impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> {
|
impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
|
fn deref(&self) -> &T { self.__data }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> {
|
impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> {
|
||||||
fn deref_mut(&mut self) -> &mut T {
|
fn deref_mut(&mut self) -> &mut T { self.__data
|
||||||
unsafe { &mut *self.__data.get() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user