about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-05-05 16:44:28 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-05-07 09:30:00 -0700
commit7529bd60c3cbc4c7b635ee43a89d5b14f6fb8bf7 (patch)
tree3497eae8c3d88f0f1b5c1e9fb3cf289b751c414e
parenta031325e83b8f050f840395239197ea87361ada5 (diff)
downloadrust-7529bd60c3cbc4c7b635ee43a89d5b14f6fb8bf7.tar.gz
rust-7529bd60c3cbc4c7b635ee43a89d5b14f6fb8bf7.zip
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.
-rw-r--r--src/libstd/sys/common/remutex.rs18
-rw-r--r--src/libstd/sys/unix/mutex.rs17
-rw-r--r--src/libstd/sys/windows/mutex.rs12
3 files changed, 25 insertions, 22 deletions
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<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
         }
     }
 
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<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) {
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<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) {