mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-17 01:13:11 +00:00
std: Remove a double-box in ReentrantMutex
Perform unsafe initialization up front and then only afterward the mutex is in place do we initialize it.
This commit is contained in:
parent
a031325e83
commit
7529bd60c3
@ -19,9 +19,9 @@ use sys::mutex as sys;
|
||||
|
||||
/// A re-entrant mutual exclusion
|
||||
///
|
||||
/// This mutex will block *other* threads waiting for the lock to become available. The thread
|
||||
/// which has already locked the mutex can lock it multiple times without blocking, preventing a
|
||||
/// common source of deadlocks.
|
||||
/// This mutex will block *other* threads waiting for the lock to become
|
||||
/// available. The thread which has already locked the mutex can lock it
|
||||
/// multiple times without blocking, preventing a common source of deadlocks.
|
||||
pub struct ReentrantMutex<T> {
|
||||
inner: Box<sys::ReentrantMutex>,
|
||||
poison: poison::Flag,
|
||||
@ -51,10 +51,14 @@ impl<'a, T> !marker::Send for ReentrantMutexGuard<'a, T> {}
|
||||
impl<T> ReentrantMutex<T> {
|
||||
/// Creates a new reentrant mutex in an unlocked state.
|
||||
pub fn new(t: T) -> ReentrantMutex<T> {
|
||||
ReentrantMutex {
|
||||
inner: box unsafe { sys::ReentrantMutex::new() },
|
||||
poison: poison::FLAG_INIT,
|
||||
data: t,
|
||||
unsafe {
|
||||
let mut mutex = ReentrantMutex {
|
||||
inner: box sys::ReentrantMutex::uninitialized(),
|
||||
poison: poison::FLAG_INIT,
|
||||
data: t,
|
||||
};
|
||||
mutex.inner.init();
|
||||
return mutex
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,30 +69,27 @@ impl Mutex {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: remove the box, because box happens twice now, once at the common layer and once here.
|
||||
// Box is necessary here, because mutex may not change address after it is intialised on some
|
||||
// platforms. Regular Mutex above handles this by offloading intialisation to the OS on first lock.
|
||||
// Sadly, as far as reentrant mutexes go, this scheme is not quite portable and we must initialise
|
||||
// when we create the mutex, in the `new`.
|
||||
pub struct ReentrantMutex { inner: Box<UnsafeCell<ffi::pthread_mutex_t>> }
|
||||
pub struct ReentrantMutex { inner: UnsafeCell<ffi::pthread_mutex_t> }
|
||||
|
||||
unsafe impl Send for ReentrantMutex {}
|
||||
unsafe impl Sync for ReentrantMutex {}
|
||||
|
||||
impl ReentrantMutex {
|
||||
pub unsafe fn new() -> ReentrantMutex {
|
||||
let mutex = ReentrantMutex { inner: box mem::uninitialized() };
|
||||
pub unsafe fn uninitialized() -> ReentrantMutex {
|
||||
ReentrantMutex { inner: mem::uninitialized() }
|
||||
}
|
||||
|
||||
pub unsafe fn init(&mut self) {
|
||||
let mut attr: ffi::pthread_mutexattr_t = mem::uninitialized();
|
||||
let result = ffi::pthread_mutexattr_init(&mut attr as *mut _);
|
||||
debug_assert_eq!(result, 0);
|
||||
let result = ffi::pthread_mutexattr_settype(&mut attr as *mut _,
|
||||
ffi::PTHREAD_MUTEX_RECURSIVE);
|
||||
debug_assert_eq!(result, 0);
|
||||
let result = ffi::pthread_mutex_init(mutex.inner.get(), &attr as *const _);
|
||||
let result = ffi::pthread_mutex_init(self.inner.get(), &attr as *const _);
|
||||
debug_assert_eq!(result, 0);
|
||||
let result = ffi::pthread_mutexattr_destroy(&mut attr as *mut _);
|
||||
debug_assert_eq!(result, 0);
|
||||
mutex
|
||||
}
|
||||
|
||||
pub unsafe fn lock(&self) {
|
||||
|
@ -59,16 +59,18 @@ impl Mutex {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReentrantMutex { inner: Box<UnsafeCell<ffi::CRITICAL_SECTION>> }
|
||||
pub struct ReentrantMutex { inner: UnsafeCell<ffi::CRITICAL_SECTION> }
|
||||
|
||||
unsafe impl Send for ReentrantMutex {}
|
||||
unsafe impl Sync for ReentrantMutex {}
|
||||
|
||||
impl ReentrantMutex {
|
||||
pub unsafe fn new() -> ReentrantMutex {
|
||||
let mutex = ReentrantMutex { inner: box mem::uninitialized() };
|
||||
ffi::InitializeCriticalSection(mutex.inner.get());
|
||||
mutex
|
||||
pub unsafe fn uninitialized() -> ReentrantMutex {
|
||||
mem::uninitialized()
|
||||
}
|
||||
|
||||
pub unsafe fn init(&mut self) {
|
||||
ffi::InitializeCriticalSection(self.inner.get());
|
||||
}
|
||||
|
||||
pub unsafe fn lock(&self) {
|
||||
|
Loading…
Reference in New Issue
Block a user