diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-05-05 16:44:28 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-05-07 09:30:00 -0700 |
| commit | 7529bd60c3cbc4c7b635ee43a89d5b14f6fb8bf7 (patch) | |
| tree | 3497eae8c3d88f0f1b5c1e9fb3cf289b751c414e | |
| parent | a031325e83b8f050f840395239197ea87361ada5 (diff) | |
| download | rust-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.rs | 18 | ||||
| -rw-r--r-- | src/libstd/sys/unix/mutex.rs | 17 | ||||
| -rw-r--r-- | src/libstd/sys/windows/mutex.rs | 12 |
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) { |
