Skip to content

Commit bd19551

Browse files
committed
Fix an apparent race in pipes.
Also removed some unsafety in pipes and added vec::consume_mut.
1 parent 110ff31 commit bd19551

File tree

2 files changed

+35
-17
lines changed

2 files changed

+35
-17
lines changed

src/libcore/pipes.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ struct packet_header {
117117
}
118118

119119
unsafe fn unblock() {
120+
assert self.state != blocked || self.blocked_task != none;
121+
self.blocked_task = none;
120122
alt swap_state_acq(self.state, empty) {
121123
empty | blocked { }
122124
terminated { self.state = terminated; }
@@ -322,7 +324,7 @@ fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
322324
rustrt::task_signal_event(
323325
task, ptr::addr_of(p.header) as *libc::c_void);
324326
}
325-
none { fail ~"blocked packet has no task" }
327+
none { debug!{"just kidding!"} }
326328
}
327329

328330
// The receiver will eventually clean this up.
@@ -878,23 +880,28 @@ struct port_set<T: send> : recv<T> {
878880

879881
fn try_recv() -> option<T> {
880882
let mut result = none;
881-
while result == none && self.ports.len() > 0 {
882-
let i = wait_many(self.ports.map(|p| p.header()));
883-
// dereferencing an unsafe pointer nonsense to appease the
884-
// borrowchecker.
885-
alt move unsafe {(*ptr::addr_of(self.ports[i])).try_recv()} {
886-
some(m) {
887-
result = some(move_it!{m});
888-
}
889-
none {
890-
// Remove this port.
891-
let mut ports = ~[];
892-
self.ports <-> ports;
893-
vec::consume(ports,
894-
|j, x| if i != j { vec::push(self.ports, x) });
895-
}
883+
// we have to swap the ports array so we aren't borrowing
884+
// aliasable mutable memory.
885+
let mut ports = ~[];
886+
ports <-> self.ports;
887+
while result == none && ports.len() > 0 {
888+
let i = wait_many(ports.map(|p| p.header()));
889+
alt move ports[i].try_recv() {
890+
some(m) {
891+
result = some(move m);
892+
}
893+
none {
894+
// Remove this port.
895+
let mut ports_ = ~[];
896+
ports <-> ports_;
897+
vec::consume(ports_,
898+
|j, x| if i != j {
899+
vec::push(ports, x)
900+
});
901+
}
896902
}
897903
}
904+
ports <-> self.ports;
898905
result
899906
}
900907

src/libcore/vec.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import libc::size_t;
66

77
export append;
88
export append_one;
9-
export consume;
9+
export consume, consume_mut;
1010
export init_op;
1111
export is_empty;
1212
export is_not_empty;
@@ -490,6 +490,17 @@ fn consume<T>(+v: ~[T], f: fn(uint, +T)) unsafe {
490490
unsafe::set_len(v, 0);
491491
}
492492

493+
fn consume_mut<T>(+v: ~[mut T], f: fn(uint, +T)) unsafe {
494+
do as_buf(v) |p, ln| {
495+
for uint::range(0, ln) |i| {
496+
let x <- *ptr::offset(p, i);
497+
f(i, x);
498+
}
499+
}
500+
501+
unsafe::set_len(v, 0);
502+
}
503+
493504
/// Remove the last element from a vector and return it
494505
fn pop<T>(&v: ~[const T]) -> T {
495506
let ln = len(v);

0 commit comments

Comments
 (0)