diff --git a/src/libstd/sys/common/remutex.rs b/src/libstd/sys/common/remutex.rs index 48c74b8d89e..1a467580672 100644 --- a/src/libstd/sys/common/remutex.rs +++ b/src/libstd/sys/common/remutex.rs @@ -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 { inner: Box, poison: poison::Flag, @@ -51,10 +51,14 @@ impl<'a, T> !marker::Send for ReentrantMutexGuard<'a, T> {} impl ReentrantMutex { /// Creates a new reentrant mutex in an unlocked state. pub fn new(t: T) -> ReentrantMutex { - 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 } } diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs index af814653c14..70d14f63dbc 100644 --- a/src/libstd/sys/unix/mutex.rs +++ b/src/libstd/sys/unix/mutex.rs @@ -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> } +pub struct ReentrantMutex { inner: UnsafeCell } 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) { diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index ca20858bb5b..9d2624f9418 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -59,16 +59,18 @@ impl Mutex { } } -pub struct ReentrantMutex { inner: Box> } +pub struct ReentrantMutex { inner: UnsafeCell } 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) {