about summary refs log tree commit diff
path: root/src/libsync
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-07 00:51:36 -0700
committerbors <bors@rust-lang.org>2014-06-07 00:51:36 -0700
commit8e9e484d7089590ce63bfe21723d7ee0c50be8f4 (patch)
tree7004b475993b711d3effe4f1694e4bfddfc29a35 /src/libsync
parent6266f64d09184f53fff4a6f7cea682b4dd714cf2 (diff)
parentf2f1991c81825b542f77b4e4f2ac65d24a063a9c (diff)
downloadrust-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.rs30
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();