Skip to content

Commit 8e9e484

Browse files
committed
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.
2 parents 6266f64 + f2f1991 commit 8e9e484

File tree

1 file changed

+8
-22
lines changed

1 file changed

+8
-22
lines changed

src/libsync/raw.rs

+8-22
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use std::kinds::marker;
1919
use std::mem;
2020
use std::sync::atomics;
21+
use std::ty::Unsafe;
2122
use std::finally::Finally;
2223

2324
use mutex;
@@ -85,11 +86,8 @@ struct Sem<Q> {
8586
// n.b, we need Sem to be `Share`, but the WaitQueue type is not send/share
8687
// (for good reason). We have an internal invariant on this semaphore,
8788
// however, that the queue is never accessed outside of a locked
88-
// context. For this reason, we shove these behind a pointer which will
89-
// be inferred to be `Share`.
90-
//
91-
// FIXME: this requires an extra allocation, which is bad.
92-
inner: *()
89+
// context.
90+
inner: Unsafe<SemInner<Q>>
9391
}
9492

9593
struct SemInner<Q> {
@@ -107,22 +105,20 @@ struct SemGuard<'a, Q> {
107105

108106
impl<Q: Send> Sem<Q> {
109107
fn new(count: int, q: Q) -> Sem<Q> {
110-
let inner = unsafe {
111-
mem::transmute(box SemInner {
108+
Sem {
109+
lock: mutex::Mutex::new(),
110+
inner: Unsafe::new(SemInner {
112111
waiters: WaitQueue::new(),
113112
count: count,
114113
blocked: q,
115114
})
116-
};
117-
Sem {
118-
lock: mutex::Mutex::new(),
119-
inner: inner,
120115
}
121116
}
122117

123118
unsafe fn with(&self, f: |&mut SemInner<Q>|) {
124119
let _g = self.lock.lock();
125-
f(&mut *(self.inner as *mut SemInner<Q>))
120+
// This &mut is safe because, due to the lock, we are the only one who can touch the data
121+
f(&mut *self.inner.get())
126122
}
127123

128124
pub fn acquire(&self) {
@@ -163,16 +159,6 @@ impl<Q: Send> Sem<Q> {
163159
}
164160
}
165161

166-
#[unsafe_destructor]
167-
impl<Q: Send> Drop for Sem<Q> {
168-
fn drop(&mut self) {
169-
let _waiters: Box<SemInner<Q>> = unsafe {
170-
mem::transmute(self.inner)
171-
};
172-
self.inner = 0 as *();
173-
}
174-
}
175-
176162
#[unsafe_destructor]
177163
impl<'a, Q: Send> Drop for SemGuard<'a, Q> {
178164
fn drop(&mut self) {

0 commit comments

Comments
 (0)