(index<- ) ./libstd/rt/message_queue.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 //! A concurrent queue that supports multiple producers and a
12 //! single consumer.
13
14 use container::Container;
15 use kinds::Send;
16 use vec::OwnedVector;
17 use cell::Cell;
18 use option::*;
19 use unstable::sync::{UnsafeArc, LittleLock};
20 use clone::Clone;
21
22 pub struct MessageQueue<T> {
23 priv state: UnsafeArc<State<T>>
24 }
25
26 struct State<T> {
27 count: uint,
28 queue: ~[T],
29 lock: LittleLock
30 }
31
32 impl<T: Send> MessageQueue<T> {
33 pub fn new() -> MessageQueue<T> {
34 MessageQueue {
35 state: UnsafeArc::new(State {
36 count: 0,
37 queue: ~[],
38 lock: LittleLock::new()
39 })
40 }
41 }
42
43 pub fn push(&mut self, value: T) {
44 unsafe {
45 let value = Cell::new(value);
46 let state = self.state.get();
47 do (*state).lock.lock {
48 (*state).count += 1;
49 (*state).queue.push(value.take());
50 }
51 }
52 }
53
54 pub fn pop(&mut self) -> Option<T> {
55 unsafe {
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())
79 } else {
80 None
81 }
82 }
83 }
84 }
85 }
86
87 impl<T: Send> Clone for MessageQueue<T> {
88 fn clone(&self) -> MessageQueue<T> {
89 MessageQueue {
90 state: self.state.clone()
91 }
92 }
93 }