Skip to content

Commit bf60078

Browse files
committed
Change MutexGuard and RwLockWriteGuard to store &mut T not &UnsafeCell<T>
This centralizes the unsafety of converting from UnsafeCell<T> to &mut T.
1 parent a4343e9 commit bf60078

File tree

2 files changed

+46
-38
lines changed

2 files changed

+46
-38
lines changed

src/libstd/sync/mutex.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ pub struct MutexGuard<'a, T: ?Sized + 'a> {
172172
// funny underscores due to how Deref/DerefMut currently work (they
173173
// disregard field privacy).
174174
__lock: &'a StaticMutex,
175-
__data: &'a UnsafeCell<T>,
175+
__data: &'a mut T,
176176
__poison: poison::Guard,
177177
}
178178

@@ -212,7 +212,7 @@ impl<T: ?Sized> Mutex<T> {
212212
#[stable(feature = "rust1", since = "1.0.0")]
213213
pub fn lock(&self) -> LockResult<MutexGuard<T>> {
214214
unsafe { self.inner.lock.lock() }
215-
MutexGuard::new(&*self.inner, &self.data)
215+
unsafe { MutexGuard::new(&*self.inner, &self.data) }
216216
}
217217

218218
/// Attempts to acquire this lock.
@@ -231,7 +231,7 @@ impl<T: ?Sized> Mutex<T> {
231231
#[stable(feature = "rust1", since = "1.0.0")]
232232
pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
233233
if unsafe { self.inner.lock.try_lock() } {
234-
Ok(try!(MutexGuard::new(&*self.inner, &self.data)))
234+
Ok(try!(unsafe { MutexGuard::new(&*self.inner, &self.data) }))
235235
} else {
236236
Err(TryLockError::WouldBlock)
237237
}
@@ -339,14 +339,14 @@ impl StaticMutex {
339339
#[inline]
340340
pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
341341
unsafe { self.lock.lock() }
342-
MutexGuard::new(self, &DUMMY.0)
342+
unsafe { MutexGuard::new(self, &DUMMY.0) }
343343
}
344344

345345
/// Attempts to grab this lock, see `Mutex::try_lock`
346346
#[inline]
347347
pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
348348
if unsafe { self.lock.try_lock() } {
349-
Ok(try!(MutexGuard::new(self, &DUMMY.0)))
349+
Ok(try!(unsafe { MutexGuard::new(self, &DUMMY.0) }))
350350
} else {
351351
Err(TryLockError::WouldBlock)
352352
}
@@ -369,12 +369,12 @@ impl StaticMutex {
369369

370370
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
371371

372-
fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
372+
unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
373373
-> LockResult<MutexGuard<'mutex, T>> {
374374
poison::map_result(lock.poison.borrow(), |guard| {
375375
MutexGuard {
376376
__lock: lock,
377-
__data: data,
377+
__data: &mut *data.get(),
378378
__poison: guard,
379379
}
380380
})
@@ -385,7 +385,10 @@ impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
385385
/// Applies the supplied closure to the data, returning a new lock
386386
/// guard referencing the borrow returned by the closure.
387387
///
388+
/// # Examples
389+
///
388390
/// ```rust
391+
/// # #![feature(guard_map)]
389392
/// # use std::sync::{Mutex, MutexGuard};
390393
/// let x = Mutex::new(vec![1, 2]);
391394
///
@@ -401,13 +404,15 @@ impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
401404
issue = "0")]
402405
pub fn map<U: ?Sized, F>(this: Self, cb: F) -> MutexGuard<'mutex, U>
403406
where F: FnOnce(&'mutex mut T) -> &'mutex mut U {
404-
let new_data = unsafe {
405-
let data = cb(&mut *this.__data.get());
406-
mem::transmute::<&'mutex mut U, &'mutex UnsafeCell<U>>(data)
407-
};
407+
// Compute the new data while still owning the original lock
408+
// in order to correctly poison if the callback panics.
409+
let data = unsafe { ptr::read(&this.__data) };
410+
let new_data = cb(data);
408411

409-
let lock = unsafe { ptr::read(&this.__lock) };
412+
// We don't want to unlock the lock by running the destructor of the
413+
// original lock, so just read the fields we need and forget it.
410414
let poison = unsafe { ptr::read(&this.__poison) };
415+
let lock = unsafe { ptr::read(&this.__lock) };
411416
mem::forget(this);
412417

413418
MutexGuard {
@@ -422,16 +427,12 @@ impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
422427
impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
423428
type Target = T;
424429

425-
fn deref(&self) -> &T {
426-
unsafe { &*self.__data.get() }
427-
}
430+
fn deref(&self) -> &T {self.__data }
428431
}
429432

430433
#[stable(feature = "rust1", since = "1.0.0")]
431434
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
432-
fn deref_mut(&mut self) -> &mut T {
433-
unsafe { &mut *self.__data.get() }
434-
}
435+
fn deref_mut(&mut self) -> &mut T { self.__data }
435436
}
436437

437438
#[stable(feature = "rust1", since = "1.0.0")]

src/libstd/sync/rwlock.rs

+27-20
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
133133
#[stable(feature = "rust1", since = "1.0.0")]
134134
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
135135
__lock: &'a StaticRwLock,
136-
__data: &'a UnsafeCell<T>,
136+
__data: &'a mut T,
137137
__poison: poison::Guard,
138138
}
139139

@@ -178,7 +178,7 @@ impl<T: ?Sized> RwLock<T> {
178178
#[stable(feature = "rust1", since = "1.0.0")]
179179
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
180180
unsafe { self.inner.lock.read() }
181-
RwLockReadGuard::new(&*self.inner, &self.data)
181+
unsafe { RwLockReadGuard::new(&*self.inner, &self.data) }
182182
}
183183

184184
/// Attempts to acquire this rwlock with shared read access.
@@ -202,7 +202,7 @@ impl<T: ?Sized> RwLock<T> {
202202
#[stable(feature = "rust1", since = "1.0.0")]
203203
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
204204
if unsafe { self.inner.lock.try_read() } {
205-
Ok(try!(RwLockReadGuard::new(&*self.inner, &self.data)))
205+
Ok(try!(unsafe { RwLockReadGuard::new(&*self.inner, &self.data) }))
206206
} else {
207207
Err(TryLockError::WouldBlock)
208208
}
@@ -226,7 +226,7 @@ impl<T: ?Sized> RwLock<T> {
226226
#[stable(feature = "rust1", since = "1.0.0")]
227227
pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
228228
unsafe { self.inner.lock.write() }
229-
RwLockWriteGuard::new(&*self.inner, &self.data)
229+
unsafe { RwLockWriteGuard::new(&*self.inner, &self.data) }
230230
}
231231

232232
/// Attempts to lock this rwlock with exclusive write access.
@@ -250,7 +250,7 @@ impl<T: ?Sized> RwLock<T> {
250250
#[stable(feature = "rust1", since = "1.0.0")]
251251
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
252252
if unsafe { self.inner.lock.try_write() } {
253-
Ok(try!(RwLockWriteGuard::new(&*self.inner, &self.data)))
253+
Ok(try!(unsafe { RwLockWriteGuard::new(&*self.inner, &self.data) }))
254254
} else {
255255
Err(TryLockError::WouldBlock)
256256
}
@@ -361,7 +361,7 @@ impl StaticRwLock {
361361
#[inline]
362362
pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> {
363363
unsafe { self.lock.read() }
364-
RwLockReadGuard::new(self, &DUMMY.0)
364+
unsafe { RwLockReadGuard::new(self, &DUMMY.0) }
365365
}
366366

367367
/// Attempts to acquire this lock with shared read access.
@@ -371,7 +371,7 @@ impl StaticRwLock {
371371
pub fn try_read(&'static self)
372372
-> TryLockResult<RwLockReadGuard<'static, ()>> {
373373
if unsafe { self.lock.try_read() } {
374-
Ok(try!(RwLockReadGuard::new(self, &DUMMY.0)))
374+
unsafe { Ok(try!(RwLockReadGuard::new(self, &DUMMY.0))) }
375375
} else {
376376
Err(TryLockError::WouldBlock)
377377
}
@@ -384,7 +384,7 @@ impl StaticRwLock {
384384
#[inline]
385385
pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> {
386386
unsafe { self.lock.write() }
387-
RwLockWriteGuard::new(self, &DUMMY.0)
387+
unsafe { RwLockWriteGuard::new(self, &DUMMY.0) }
388388
}
389389

390390
/// Attempts to lock this rwlock with exclusive write access.
@@ -394,7 +394,7 @@ impl StaticRwLock {
394394
pub fn try_write(&'static self)
395395
-> TryLockResult<RwLockWriteGuard<'static, ()>> {
396396
if unsafe { self.lock.try_write() } {
397-
Ok(try!(RwLockWriteGuard::new(self, &DUMMY.0)))
397+
Ok(unsafe { try!(RwLockWriteGuard::new(self, &DUMMY.0)) })
398398
} else {
399399
Err(TryLockError::WouldBlock)
400400
}
@@ -412,12 +412,12 @@ impl StaticRwLock {
412412
}
413413

414414
impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
415-
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
415+
unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
416416
-> LockResult<RwLockReadGuard<'rwlock, T>> {
417417
poison::map_result(lock.poison.borrow(), |_| {
418418
RwLockReadGuard {
419419
__lock: lock,
420-
__data: unsafe { &*data.get() },
420+
__data: &*data.get(),
421421
}
422422
})
423423
}
@@ -427,7 +427,10 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
427427
/// Applies the supplied closure to the data, returning a new lock
428428
/// guard referencing the borrow returned by the closure.
429429
///
430+
/// # Examples
431+
///
430432
/// ```rust
433+
/// # #![feature(guard_map)]
431434
/// # use std::sync::{RwLockReadGuard, RwLock};
432435
/// let x = RwLock::new(vec![1, 2]);
433436
///
@@ -451,12 +454,12 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
451454
}
452455

453456
impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
454-
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
457+
unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
455458
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
456459
poison::map_result(lock.poison.borrow(), |guard| {
457460
RwLockWriteGuard {
458461
__lock: lock,
459-
__data: data,
462+
__data: &mut *data.get(),
460463
__poison: guard,
461464
}
462465
})
@@ -467,7 +470,10 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
467470
/// Applies the supplied closure to the data, returning a new lock
468471
/// guard referencing the borrow returned by the closure.
469472
///
473+
/// # Examples
474+
///
470475
/// ```rust
476+
/// # #![feature(guard_map)]
471477
/// # use std::sync::{RwLockWriteGuard, RwLock};
472478
/// let x = RwLock::new(vec![1, 2]);
473479
///
@@ -485,11 +491,13 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
485491
issue = "0")]
486492
pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockWriteGuard<'rwlock, U>
487493
where F: FnOnce(&'rwlock mut T) -> &'rwlock mut U {
488-
let new_data = unsafe {
489-
let data: &'rwlock mut T = &mut *this.__data.get();
490-
mem::transmute::<&'rwlock mut U, &'rwlock UnsafeCell<U>>(cb(data))
491-
};
494+
// Compute the new data while still owning the original lock
495+
// in order to correctly poison if the callback panics.
496+
let data = unsafe { ptr::read(&this.__data) };
497+
let new_data = cb(data);
492498

499+
// We don't want to unlock the lock by running the destructor of the
500+
// original lock, so just read the fields we need and forget it.
493501
let poison = unsafe { ptr::read(&this.__poison) };
494502
let lock = unsafe { ptr::read(&this.__lock) };
495503
mem::forget(this);
@@ -513,13 +521,12 @@ impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> {
513521
impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> {
514522
type Target = T;
515523

516-
fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
524+
fn deref(&self) -> &T { self.__data }
517525
}
518526

519527
#[stable(feature = "rust1", since = "1.0.0")]
520528
impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> {
521-
fn deref_mut(&mut self) -> &mut T {
522-
unsafe { &mut *self.__data.get() }
529+
fn deref_mut(&mut self) -> &mut T { self.__data
523530
}
524531
}
525532

0 commit comments

Comments
 (0)