diff options
| author | Brian Anderson <banderson@mozilla.com> | 2013-08-17 19:55:22 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-08-24 15:46:03 -0700 |
| commit | 0fff8b6549868b3355e3219e19db11ddf8e46c60 (patch) | |
| tree | e1fcae112bb4c03f681aee766f5683a642b86c6e /src/libstd/rt/message_queue.rs | |
| parent | 5d04234868428fe819fb17d78b8f7468161586b9 (diff) | |
| download | rust-0fff8b6549868b3355e3219e19db11ddf8e46c60.tar.gz rust-0fff8b6549868b3355e3219e19db11ddf8e46c60.zip | |
std::rt: Reduce MessageQueue contention
It's not a huge win but it does reduce the amount of time spent contesting the message queue when the schedulers are under load
Diffstat (limited to 'src/libstd/rt/message_queue.rs')
| -rw-r--r-- | src/libstd/rt/message_queue.rs | 50 |
1 files changed, 42 insertions, 8 deletions
diff --git a/src/libstd/rt/message_queue.rs b/src/libstd/rt/message_queue.rs index d58c0120803..2bbcaff6d28 100644 --- a/src/libstd/rt/message_queue.rs +++ b/src/libstd/rt/message_queue.rs @@ -16,32 +16,66 @@ use kinds::Send; use vec::OwnedVector; use cell::Cell; use option::*; -use unstable::sync::Exclusive; +use unstable::sync::{UnsafeAtomicRcBox, LittleLock}; use clone::Clone; pub struct MessageQueue<T> { - priv queue: Exclusive<~[T]> + priv state: UnsafeAtomicRcBox<State<T>> +} + +struct State<T> { + count: uint, + queue: ~[T], + lock: LittleLock } impl<T: Send> MessageQueue<T> { pub fn new() -> MessageQueue<T> { MessageQueue { - queue: Exclusive::new(~[]) + state: UnsafeAtomicRcBox::new(State { + count: 0, + queue: ~[], + lock: LittleLock::new() + }) } } pub fn push(&mut self, value: T) { unsafe { let value = Cell::new(value); - self.queue.with(|q| q.push(value.take()) ); + let state = self.state.get(); + do (*state).lock.lock { + (*state).count += 1; + (*state).queue.push(value.take()); + } } } pub fn pop(&mut self) -> Option<T> { unsafe { - do self.queue.with |q| { - if !q.is_empty() { - Some(q.shift()) + let state = self.state.get(); + do (*state).lock.lock { + if !(*state).queue.is_empty() { + (*state).count += 1; + Some((*state).queue.shift()) + } else { + None + } + } + } + } + + /// A pop that may sometimes miss enqueued elements, but is much faster + /// to give up without doing any synchronization + pub fn casual_pop(&mut self) -> Option<T> { + unsafe { + let state = self.state.get(); + // NB: Unsynchronized check + if (*state).count == 0 { return None; } + do (*state).lock.lock { + if !(*state).queue.is_empty() { + (*state).count += 1; + Some((*state).queue.shift()) } else { None } @@ -53,7 +87,7 @@ impl<T: Send> MessageQueue<T> { impl<T: Send> Clone for MessageQueue<T> { fn clone(&self) -> MessageQueue<T> { MessageQueue { - queue: self.queue.clone() + state: self.state.clone() } } } |
