diff options
| author | bors <bors@rust-lang.org> | 2014-06-07 00:51:36 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-06-07 00:51:36 -0700 |
| commit | 8e9e484d7089590ce63bfe21723d7ee0c50be8f4 (patch) | |
| tree | 7004b475993b711d3effe4f1694e4bfddfc29a35 /src/libsync | |
| parent | 6266f64d09184f53fff4a6f7cea682b4dd714cf2 (diff) | |
| parent | f2f1991c81825b542f77b4e4f2ac65d24a063a9c (diff) | |
| download | rust-8e9e484d7089590ce63bfe21723d7ee0c50be8f4.tar.gz rust-8e9e484d7089590ce63bfe21723d7ee0c50be8f4.zip | |
auto merge of #14708 : gereeter/rust/faster-sem, r=alexcrichton
Currently, `Sem`, which is used as a building block for all the blocking primitives, uses a very ugly hack to implement `Share` and be able to mutate the stored `WaitQueue` by hiding it all behind a `transmute`d `*()`. This PR replaces all that ugly machinery with `Unsafe`. Beyond being cleaner and not requiring `transmute`, this removes an allocation in the creation and removes an indirection for access.
Diffstat (limited to 'src/libsync')
| -rw-r--r-- | src/libsync/raw.rs | 30 |
1 files changed, 8 insertions, 22 deletions
diff --git a/src/libsync/raw.rs b/src/libsync/raw.rs index aae790f887a..8fd10cdfa8b 100644 --- a/src/libsync/raw.rs +++ b/src/libsync/raw.rs @@ -18,6 +18,7 @@ use std::kinds::marker; use std::mem; use std::sync::atomics; +use std::ty::Unsafe; use std::finally::Finally; use mutex; @@ -85,11 +86,8 @@ struct Sem<Q> { // n.b, we need Sem to be `Share`, but the WaitQueue type is not send/share // (for good reason). We have an internal invariant on this semaphore, // however, that the queue is never accessed outside of a locked - // context. For this reason, we shove these behind a pointer which will - // be inferred to be `Share`. - // - // FIXME: this requires an extra allocation, which is bad. - inner: *() + // context. + inner: Unsafe<SemInner<Q>> } struct SemInner<Q> { @@ -107,22 +105,20 @@ struct SemGuard<'a, Q> { impl<Q: Send> Sem<Q> { fn new(count: int, q: Q) -> Sem<Q> { - let inner = unsafe { - mem::transmute(box SemInner { + Sem { + lock: mutex::Mutex::new(), + inner: Unsafe::new(SemInner { waiters: WaitQueue::new(), count: count, blocked: q, }) - }; - Sem { - lock: mutex::Mutex::new(), - inner: inner, } } unsafe fn with(&self, f: |&mut SemInner<Q>|) { let _g = self.lock.lock(); - f(&mut *(self.inner as *mut SemInner<Q>)) + // This &mut is safe because, due to the lock, we are the only one who can touch the data + f(&mut *self.inner.get()) } pub fn acquire(&self) { @@ -164,16 +160,6 @@ impl<Q: Send> Sem<Q> { } #[unsafe_destructor] -impl<Q: Send> Drop for Sem<Q> { - fn drop(&mut self) { - let _waiters: Box<SemInner<Q>> = unsafe { - mem::transmute(self.inner) - }; - self.inner = 0 as *(); - } -} - -#[unsafe_destructor] impl<'a, Q: Send> Drop for SemGuard<'a, Q> { fn drop(&mut self) { self.sem.release(); |
