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.
This commit is contained in:
bors 2014-06-07 00:51:36 -07:00
commit 8e9e484d70

View File

@ -18,6 +18,7 @@
use std::kinds::marker; use std::kinds::marker;
use std::mem; use std::mem;
use std::sync::atomics; use std::sync::atomics;
use std::ty::Unsafe;
use std::finally::Finally; use std::finally::Finally;
use mutex; 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 // 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, // (for good reason). We have an internal invariant on this semaphore,
// however, that the queue is never accessed outside of a locked // however, that the queue is never accessed outside of a locked
// context. For this reason, we shove these behind a pointer which will // context.
// be inferred to be `Share`. inner: Unsafe<SemInner<Q>>
//
// FIXME: this requires an extra allocation, which is bad.
inner: *()
} }
struct SemInner<Q> { struct SemInner<Q> {
@ -107,22 +105,20 @@ struct SemGuard<'a, Q> {
impl<Q: Send> Sem<Q> { impl<Q: Send> Sem<Q> {
fn new(count: int, q: Q) -> Sem<Q> { fn new(count: int, q: Q) -> Sem<Q> {
let inner = unsafe { Sem {
mem::transmute(box SemInner { lock: mutex::Mutex::new(),
inner: Unsafe::new(SemInner {
waiters: WaitQueue::new(), waiters: WaitQueue::new(),
count: count, count: count,
blocked: q, blocked: q,
}) })
};
Sem {
lock: mutex::Mutex::new(),
inner: inner,
} }
} }
unsafe fn with(&self, f: |&mut SemInner<Q>|) { unsafe fn with(&self, f: |&mut SemInner<Q>|) {
let _g = self.lock.lock(); 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) { pub fn acquire(&self) {
@ -163,16 +159,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] #[unsafe_destructor]
impl<'a, Q: Send> Drop for SemGuard<'a, Q> { impl<'a, Q: Send> Drop for SemGuard<'a, Q> {
fn drop(&mut self) { fn drop(&mut self) {