(index<- ) ./libstd/rt/sleeper_list.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Maintains a shared list of sleeping schedulers. Schedulers
12 //! use this to wake each other up.
13
14 use container::Container;
15 use vec::OwnedVector;
16 use option::{Option, Some, None};
17 use cell::Cell;
18 use unstable::sync::{UnsafeArc, LittleLock};
19 use rt::sched::SchedHandle;
20 use clone::Clone;
21
22 pub struct SleeperList {
23 priv state: UnsafeArc<State>
24 }
25
26 struct State {
27 count: uint,
28 stack: ~[SchedHandle],
29 lock: LittleLock
30 }
31
32 impl SleeperList {
33 pub fn new() -> SleeperList {
34 SleeperList {
35 state: UnsafeArc::new(State {
36 count: 0,
37 stack: ~[],
38 lock: LittleLock::new()
39 })
40 }
41 }
42
43 pub fn push(&mut self, handle: SchedHandle) {
44 let handle = Cell::new(handle);
45 unsafe {
46 let state = self.state.get();
47 do (*state).lock.lock {
48 (*state).count += 1;
49 (*state).stack.push(handle.take());
50 }
51 }
52 }
53
54 pub fn pop(&mut self) -> Option<SchedHandle> {
55 unsafe {
56 let state = self.state.get();
57 do (*state).lock.lock {
58 if !(*state).stack.is_empty() {
59 (*state).count -= 1;
60 Some((*state).stack.pop())
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<SchedHandle> {
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).stack.is_empty() {
77 // NB: count is also protected by the lock
78 (*state).count -= 1;
79 Some((*state).stack.pop())
80 } else {
81 None
82 }
83 }
84 }
85 }
86 }
87
88 impl Clone for SleeperList {
89 fn clone(&self) -> SleeperList {
90 SleeperList {
91 state: self.state.clone()
92 }
93 }
94 }