Skip to content

Commit a45e508

Browse files
committed
---
yaml --- r: 144366 b: refs/heads/try2 c: 0fff8b6 h: refs/heads/master v: v3
1 parent f3494b8 commit a45e508

File tree

3 files changed

+70
-13
lines changed

3 files changed

+70
-13
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 5d04234868428fe819fb17d78b8f7468161586b9
8+
refs/heads/try2: 0fff8b6549868b3355e3219e19db11ddf8e46c60
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libstd/rt/message_queue.rs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,66 @@ use kinds::Send;
1616
use vec::OwnedVector;
1717
use cell::Cell;
1818
use option::*;
19-
use unstable::sync::Exclusive;
19+
use unstable::sync::{UnsafeAtomicRcBox, LittleLock};
2020
use clone::Clone;
2121

2222
pub struct MessageQueue<T> {
23-
priv queue: Exclusive<~[T]>
23+
priv state: UnsafeAtomicRcBox<State<T>>
24+
}
25+
26+
struct State<T> {
27+
count: uint,
28+
queue: ~[T],
29+
lock: LittleLock
2430
}
2531

2632
impl<T: Send> MessageQueue<T> {
2733
pub fn new() -> MessageQueue<T> {
2834
MessageQueue {
29-
queue: Exclusive::new(~[])
35+
state: UnsafeAtomicRcBox::new(State {
36+
count: 0,
37+
queue: ~[],
38+
lock: LittleLock::new()
39+
})
3040
}
3141
}
3242

3343
pub fn push(&mut self, value: T) {
3444
unsafe {
3545
let value = Cell::new(value);
36-
self.queue.with(|q| q.push(value.take()) );
46+
let state = self.state.get();
47+
do (*state).lock.lock {
48+
(*state).count += 1;
49+
(*state).queue.push(value.take());
50+
}
3751
}
3852
}
3953

4054
pub fn pop(&mut self) -> Option<T> {
4155
unsafe {
42-
do self.queue.with |q| {
43-
if !q.is_empty() {
44-
Some(q.shift())
56+
let state = self.state.get();
57+
do (*state).lock.lock {
58+
if !(*state).queue.is_empty() {
59+
(*state).count += 1;
60+
Some((*state).queue.shift())
61+
} else {
62+
None
63+
}
64+
}
65+
}
66+
}
67+
68+
/// A pop that may sometimes miss enqueued elements, but is much faster
69+
/// to give up without doing any synchronization
70+
pub fn casual_pop(&mut self) -> Option<T> {
71+
unsafe {
72+
let state = self.state.get();
73+
// NB: Unsynchronized check
74+
if (*state).count == 0 { return None; }
75+
do (*state).lock.lock {
76+
if !(*state).queue.is_empty() {
77+
(*state).count += 1;
78+
Some((*state).queue.shift())
4579
} else {
4680
None
4781
}
@@ -53,7 +87,7 @@ impl<T: Send> MessageQueue<T> {
5387
impl<T: Send> Clone for MessageQueue<T> {
5488
fn clone(&self) -> MessageQueue<T> {
5589
MessageQueue {
56-
queue: self.queue.clone()
90+
state: self.state.clone()
5791
}
5892
}
5993
}

branches/try2/src/libstd/rt/sched.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ pub struct Scheduler {
8383
idle_callback: Option<~PausibleIdleCallback>
8484
}
8585

86+
/// An indication of how hard to work on a given operation, the difference
87+
/// mainly being whether memory is synchronized or not
88+
#[deriving(Eq)]
89+
enum EffortLevel {
90+
DontTryTooHard,
91+
GiveItYourBest
92+
}
93+
8694
impl Scheduler {
8795

8896
// * Initialization Functions
@@ -237,14 +245,21 @@ impl Scheduler {
237245

238246
// First we check for scheduler messages, these are higher
239247
// priority than regular tasks.
240-
let sched = match sched.interpret_message_queue() {
248+
let sched = match sched.interpret_message_queue(DontTryTooHard) {
241249
Some(sched) => sched,
242250
None => return
243251
};
244252

245253
// This helper will use a randomized work-stealing algorithm
246254
// to find work.
247-
let mut sched = match sched.do_work() {
255+
let sched = match sched.do_work() {
256+
Some(sched) => sched,
257+
None => return
258+
};
259+
260+
// Now, before sleeping we need to find out if there really
261+
// were any messages. Give it your best!
262+
let mut sched = match sched.interpret_message_queue(GiveItYourBest) {
248263
Some(sched) => sched,
249264
None => return
250265
};
@@ -277,10 +292,18 @@ impl Scheduler {
277292
// returns the still-available scheduler. At this point all
278293
// message-handling will count as a turn of work, and as a result
279294
// return None.
280-
fn interpret_message_queue(~self) -> Option<~Scheduler> {
295+
fn interpret_message_queue(~self, effort: EffortLevel) -> Option<~Scheduler> {
281296

282297
let mut this = self;
283-
match this.message_queue.pop() {
298+
299+
let msg = if effort == DontTryTooHard {
300+
// Do a cheap check that may miss messages
301+
this.message_queue.casual_pop()
302+
} else {
303+
this.message_queue.pop()
304+
};
305+
306+
match msg {
284307
Some(PinnedTask(task)) => {
285308
let mut task = task;
286309
task.give_home(Sched(this.make_handle()));

0 commit comments

Comments
 (0)