Skip to content

Commit 2966e97

Browse files
committed
std: Rebuild mpsc queue with Unsafe/&self
This removes the incorrect `&mut self` taken because it can alias among many threads.
1 parent 7db02e2 commit 2966e97

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

src/libstd/sync/mpsc_queue.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use option::{Option, None, Some};
4545
use owned::Box;
4646
use ptr::RawPtr;
4747
use sync::atomics::{AtomicPtr, Release, Acquire, AcqRel, Relaxed};
48+
use ty::Unsafe;
4849

4950
/// A result of the `pop` function.
5051
pub enum PopResult<T> {
@@ -69,7 +70,7 @@ struct Node<T> {
6970
/// popper at a time (many pushers are allowed).
7071
pub struct Queue<T> {
7172
head: AtomicPtr<Node<T>>,
72-
tail: *mut Node<T>,
73+
tail: Unsafe<*mut Node<T>>,
7374
}
7475

7576
impl<T> Node<T> {
@@ -88,12 +89,12 @@ impl<T: Send> Queue<T> {
8889
let stub = unsafe { Node::new(None) };
8990
Queue {
9091
head: AtomicPtr::new(stub),
91-
tail: stub,
92+
tail: Unsafe::new(stub),
9293
}
9394
}
9495

9596
/// Pushes a new value onto this queue.
96-
pub fn push(&mut self, t: T) {
97+
pub fn push(&self, t: T) {
9798
unsafe {
9899
let n = Node::new(Some(t));
99100
let prev = self.head.swap(n, AcqRel);
@@ -111,13 +112,13 @@ impl<T: Send> Queue<T> {
111112
///
112113
/// This inconsistent state means that this queue does indeed have data, but
113114
/// it does not currently have access to it at this time.
114-
pub fn pop(&mut self) -> PopResult<T> {
115+
pub fn pop(&self) -> PopResult<T> {
115116
unsafe {
116-
let tail = self.tail;
117+
let tail = *self.tail.get();
117118
let next = (*tail).next.load(Acquire);
118119

119120
if !next.is_null() {
120-
self.tail = next;
121+
*self.tail.get() = next;
121122
assert!((*tail).value.is_none());
122123
assert!((*next).value.is_some());
123124
let ret = (*next).value.take_unwrap();
@@ -131,7 +132,7 @@ impl<T: Send> Queue<T> {
131132

132133
/// Attempts to pop data from this queue, but doesn't attempt too hard. This
133134
/// will canonicalize inconsistent states to a `None` value.
134-
pub fn casual_pop(&mut self) -> Option<T> {
135+
pub fn casual_pop(&self) -> Option<T> {
135136
match self.pop() {
136137
Data(t) => Some(t),
137138
Empty | Inconsistent => None,
@@ -143,7 +144,7 @@ impl<T: Send> Queue<T> {
143144
impl<T: Send> Drop for Queue<T> {
144145
fn drop(&mut self) {
145146
unsafe {
146-
let mut cur = self.tail;
147+
let mut cur = *self.tail.get();
147148
while !cur.is_null() {
148149
let next = (*cur).next.load(Relaxed);
149150
let _: Box<Node<T>> = mem::transmute(cur);

0 commit comments

Comments
 (0)