Skip to content

Commit e3142c5

Browse files
committed
auto merge of #7858 : bblum/rust/kill, r=brson
Some notes about the commits. Exit code propagation commits: * ```Reimplement unwrap()``` has the same old code from ```arc::unwrap``` ported to use modern atomic types and finally (it's considerably nicer this way) * ```Add try_unwrap()``` has some new slightly-tricky (but pretty simple) concurrency primitive code * ```Add KillHandle``` and ```Add kill::Death``` are the bulk of the logic. Task killing commits: * ```Implement KillHandle::kill() and friends```, ```Do a task-killed check```, and ```Add BlockedTask``` implement the killing logic; * ```Change the HOF context switchers``` turns said logic on Linked failure commits: * ```Replace *rust_task ptrs``` adapts the taskgroup code to work for both runtimes * ```Enable taskgroup code``` does what it says on the tin. r? @brson
2 parents fdbd56c + 980646a commit e3142c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1979
-1254
lines changed

src/libextra/arc.rs

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ use std::borrow;
5050

5151
/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
5252
pub struct Condvar<'self> {
53-
is_mutex: bool,
54-
failed: &'self mut bool,
55-
cond: &'self sync::Condvar<'self>
53+
priv is_mutex: bool,
54+
priv failed: &'self mut bool,
55+
priv cond: &'self sync::Condvar<'self>
5656
}
5757

5858
impl<'self> Condvar<'self> {
@@ -108,7 +108,7 @@ impl<'self> Condvar<'self> {
108108
****************************************************************************/
109109

110110
/// An atomically reference counted wrapper for shared immutable state.
111-
pub struct ARC<T> { x: UnsafeAtomicRcBox<T> }
111+
pub struct ARC<T> { priv x: UnsafeAtomicRcBox<T> }
112112

113113
/// Create an atomically reference counted wrapper.
114114
pub fn ARC<T:Freeze + Send>(data: T) -> ARC<T> {
@@ -123,6 +123,20 @@ impl<T:Freeze+Send> ARC<T> {
123123
pub fn get<'a>(&'a self) -> &'a T {
124124
unsafe { &*self.x.get_immut() }
125125
}
126+
127+
/**
128+
* Retrieve the data back out of the ARC. This function blocks until the
129+
* reference given to it is the last existing one, and then unwrap the data
130+
* instead of destroying it.
131+
*
132+
* If multiple tasks call unwrap, all but the first will fail. Do not call
133+
* unwrap from a task that holds another reference to the same ARC; it is
134+
* guaranteed to deadlock.
135+
*/
136+
pub fn unwrap(self) -> T {
137+
let ARC { x: x } = self;
138+
unsafe { x.unwrap() }
139+
}
126140
}
127141

128142
/**
@@ -143,9 +157,9 @@ impl<T:Freeze + Send> Clone for ARC<T> {
143157
****************************************************************************/
144158

145159
#[doc(hidden)]
146-
struct MutexARCInner<T> { lock: Mutex, failed: bool, data: T }
160+
struct MutexARCInner<T> { priv lock: Mutex, priv failed: bool, priv data: T }
147161
/// An ARC with mutable data protected by a blocking mutex.
148-
struct MutexARC<T> { x: UnsafeAtomicRcBox<MutexARCInner<T>> }
162+
struct MutexARC<T> { priv x: UnsafeAtomicRcBox<MutexARCInner<T>> }
149163

150164
/// Create a mutex-protected ARC with the supplied data.
151165
pub fn MutexARC<T:Send>(user_data: T) -> MutexARC<T> {
@@ -225,6 +239,22 @@ impl<T:Send> MutexARC<T> {
225239
cond: cond })
226240
}
227241
}
242+
243+
/**
244+
* Retrieves the data, blocking until all other references are dropped,
245+
* exactly as arc::unwrap.
246+
*
247+
* Will additionally fail if another task has failed while accessing the arc.
248+
*/
249+
pub fn unwrap(self) -> T {
250+
let MutexARC { x: x } = self;
251+
let inner = unsafe { x.unwrap() };
252+
let MutexARCInner { failed: failed, data: data, _ } = inner;
253+
if failed {
254+
fail!(~"Can't unwrap poisoned MutexARC - another task failed inside!");
255+
}
256+
data
257+
}
228258
}
229259
230260
// Common code for {mutex.access,rwlock.write}{,_cond}.
@@ -268,7 +298,7 @@ fn PoisonOnFail<'r>(failed: &'r mut bool) -> PoisonOnFail {
268298
****************************************************************************/
269299
270300
#[doc(hidden)]
271-
struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
301+
struct RWARCInner<T> { priv lock: RWlock, priv failed: bool, priv data: T }
272302
/**
273303
* A dual-mode ARC protected by a reader-writer lock. The data can be accessed
274304
* mutably or immutably, and immutably-accessing tasks may run concurrently.
@@ -278,7 +308,7 @@ struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
278308
#[mutable] // XXX remove after snap
279309
#[no_freeze]
280310
struct RWARC<T> {
281-
x: UnsafeAtomicRcBox<RWARCInner<T>>,
311+
priv x: UnsafeAtomicRcBox<RWARCInner<T>>,
282312
}
283313
284314
/// Create a reader/writer ARC with the supplied data.
@@ -429,6 +459,23 @@ impl<T:Freeze + Send> RWARC<T> {
429459
}
430460
}
431461
}
462+
463+
/**
464+
* Retrieves the data, blocking until all other references are dropped,
465+
* exactly as arc::unwrap.
466+
*
467+
* Will additionally fail if another task has failed while accessing the arc
468+
* in write mode.
469+
*/
470+
pub fn unwrap(self) -> T {
471+
let RWARC { x: x, _ } = self;
472+
let inner = unsafe { x.unwrap() };
473+
let RWARCInner { failed: failed, data: data, _ } = inner;
474+
if failed {
475+
fail!(~"Can't unwrap poisoned RWARC - another task failed inside!")
476+
}
477+
data
478+
}
432479
}
433480
434481
// Borrowck rightly complains about immutably aliasing the rwlock in order to
@@ -611,6 +658,23 @@ mod tests {
611658
}
612659
}
613660
#[test] #[should_fail] #[ignore(cfg(windows))]
661+
pub fn test_mutex_arc_unwrap_poison() {
662+
let arc = MutexARC(1);
663+
let arc2 = ~(&arc).clone();
664+
let (p, c) = comm::stream();
665+
do task::spawn {
666+
unsafe {
667+
do arc2.access |one| {
668+
c.send(());
669+
assert!(*one == 2);
670+
}
671+
}
672+
}
673+
let _ = p.recv();
674+
let one = arc.unwrap();
675+
assert!(one == 1);
676+
}
677+
#[test] #[should_fail] #[ignore(cfg(windows))]
614678
fn test_rw_arc_poison_wr() {
615679
let arc = ~RWARC(1);
616680
let arc2 = (*arc).clone();

src/libextra/dlist.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl<T> Deque<T> for DList<T> {
208208
///
209209
/// O(1)
210210
fn pop_front(&mut self) -> Option<T> {
211-
match util::replace(&mut self.list_head, None) {
211+
match self.list_head.take() {
212212
None => None,
213213
Some(old_head) => {
214214
self.length -= 1;

src/libextra/ringbuf.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
//! extra::container::Deque`.
1515
1616
use std::num;
17-
use std::util;
1817
use std::uint;
1918
use std::vec;
2019
use std::iterator::{FromIterator, InvertIterator};
@@ -72,7 +71,7 @@ impl<T> Deque<T> for RingBuf<T> {
7271

7372
/// Remove and return the first element in the RingBuf, or None if it is empty
7473
fn pop_front(&mut self) -> Option<T> {
75-
let result = util::replace(&mut self.elts[self.lo], None);
74+
let result = self.elts[self.lo].take();
7675
if result.is_some() {
7776
self.lo = (self.lo + 1u) % self.elts.len();
7877
self.nelts -= 1u;
@@ -85,7 +84,7 @@ impl<T> Deque<T> for RingBuf<T> {
8584
if self.nelts > 0 {
8685
self.nelts -= 1;
8786
let hi = self.raw_index(self.nelts);
88-
util::replace(&mut self.elts[hi], None)
87+
self.elts[hi].take()
8988
} else {
9089
None
9190
}

src/libextra/smallintmap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl<V> MutableMap<uint, V> for SmallIntMap<V> {
118118
if *key >= self.v.len() {
119119
return None;
120120
}
121-
replace(&mut self.v[*key], None)
121+
self.v[*key].take()
122122
}
123123
}
124124

src/libextra/sort.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,8 +1020,6 @@ mod big_tests {
10201020

10211021
use sort::*;
10221022

1023-
use std::cast::unsafe_copy;
1024-
use std::local_data;
10251023
use std::rand::RngUtil;
10261024
use std::rand;
10271025
use std::uint;

src/libextra/treemap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
697697
}
698698
}
699699
}
700-
return match replace(node, None) {
700+
return match node.take() {
701701
Some(~TreeNode{value, _}) => Some(value), None => fail!()
702702
};
703703
}

src/libextra/workcache.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ use std::result;
2727
use std::run;
2828
use std::task;
2929
use std::to_bytes;
30-
use std::util::replace;
3130

3231
/**
3332
*
@@ -353,7 +352,7 @@ impl TPrep for Prep {
353352

354353
_ => {
355354
let (port, chan) = oneshot();
356-
let blk = replace(&mut bo, None).unwrap();
355+
let blk = bo.take_unwrap();
357356
let chan = Cell::new(chan);
358357

359358
do task::spawn {
@@ -385,7 +384,7 @@ fn unwrap<T:Send +
385384
Decodable<json::Decoder>>( // FIXME(#5121)
386385
w: Work<T>) -> T {
387386
let mut ww = w;
388-
let s = replace(&mut ww.res, None);
387+
let s = ww.res.take();
389388

390389
match s {
391390
None => fail!(),

src/libstd/cell.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
use cast::transmute_mut;
1616
use prelude::*;
17-
use util::replace;
1817

1918
/*
2019
A dynamic, mutable location.
@@ -48,7 +47,7 @@ impl<T> Cell<T> {
4847
fail!("attempt to take an empty cell");
4948
}
5049

51-
replace(&mut this.value, None).unwrap()
50+
this.value.take_unwrap()
5251
}
5352

5453
/// Returns the value, failing if the cell is full.

src/libstd/comm.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,7 @@ impl<T: Send> GenericChan<T> for SharedChan<T> {
242242
unsafe {
243243
let mut xx = Some(x);
244244
do chan.with_imm |chan| {
245-
let x = replace(&mut xx, None);
246-
chan.send(x.unwrap())
245+
chan.send(xx.take_unwrap())
247246
}
248247
}
249248
}
@@ -259,8 +258,7 @@ impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
259258
unsafe {
260259
let mut xx = Some(x);
261260
do chan.with_imm |chan| {
262-
let x = replace(&mut xx, None);
263-
chan.try_send(x.unwrap())
261+
chan.try_send(xx.take_unwrap())
264262
}
265263
}
266264
}
@@ -372,7 +370,6 @@ mod pipesy {
372370
use pipes::{recv, try_recv, peek, PacketHeader};
373371
use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable};
374372
use cast::transmute_mut;
375-
use util::replace;
376373

377374
/*proto! oneshot (
378375
Oneshot:send<T:Send> {
@@ -638,8 +635,7 @@ mod pipesy {
638635
fn send(&self, x: T) {
639636
unsafe {
640637
let self_endp = transmute_mut(&self.endp);
641-
let endp = replace(self_endp, None);
642-
*self_endp = Some(streamp::client::data(endp.unwrap(), x))
638+
*self_endp = Some(streamp::client::data(self_endp.take_unwrap(), x))
643639
}
644640
}
645641
}
@@ -649,8 +645,7 @@ mod pipesy {
649645
fn try_send(&self, x: T) -> bool {
650646
unsafe {
651647
let self_endp = transmute_mut(&self.endp);
652-
let endp = replace(self_endp, None);
653-
match streamp::client::try_data(endp.unwrap(), x) {
648+
match streamp::client::try_data(self_endp.take_unwrap(), x) {
654649
Some(next) => {
655650
*self_endp = Some(next);
656651
true
@@ -666,7 +661,7 @@ mod pipesy {
666661
fn recv(&self) -> T {
667662
unsafe {
668663
let self_endp = transmute_mut(&self.endp);
669-
let endp = replace(self_endp, None);
664+
let endp = self_endp.take();
670665
let streamp::data(x, endp) = recv(endp.unwrap());
671666
*self_endp = Some(endp);
672667
x
@@ -677,7 +672,7 @@ mod pipesy {
677672
fn try_recv(&self) -> Option<T> {
678673
unsafe {
679674
let self_endp = transmute_mut(&self.endp);
680-
let endp = replace(self_endp, None);
675+
let endp = self_endp.take();
681676
match try_recv(endp.unwrap()) {
682677
Some(streamp::data(x, endp)) => {
683678
*self_endp = Some(endp);
@@ -694,7 +689,7 @@ mod pipesy {
694689
fn peek(&self) -> bool {
695690
unsafe {
696691
let self_endp = transmute_mut(&self.endp);
697-
let mut endp = replace(self_endp, None);
692+
let mut endp = self_endp.take();
698693
let peek = match endp {
699694
Some(ref mut endp) => peek(endp),
700695
None => fail!("peeking empty stream")

src/libstd/either.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use cmp::Eq;
1818
use iterator::IteratorUtil;
1919
use result::Result;
2020
use result;
21+
use str::StrSlice;
2122
use vec;
2223
use vec::{OwnedVector, ImmutableVector};
2324

@@ -121,24 +122,37 @@ pub fn is_right<T, U>(eith: &Either<T, U>) -> bool {
121122
}
122123
}
123124

124-
/// Retrieves the value in the left branch. Fails if the either is Right.
125+
/// Retrieves the value in the left branch.
126+
/// Fails with a specified reason if the either is Right.
125127
#[inline]
126-
pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
128+
pub fn expect_left<T,U>(eith: Either<T,U>, reason: &str) -> T {
127129
match eith {
128130
Left(x) => x,
129-
Right(_) => fail!("either::unwrap_left Right")
131+
Right(_) => fail!(reason.to_owned())
130132
}
131133
}
132134

133-
/// Retrieves the value in the right branch. Fails if the either is Left.
135+
/// Retrieves the value in the left branch. Fails if the either is Right.
134136
#[inline]
135-
pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
137+
pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
138+
expect_left(eith, "either::unwrap_left Right")
139+
}
140+
141+
/// Retrieves the value in the right branch.
142+
/// Fails with a specified reason if the either is Left.
143+
#[inline]
144+
pub fn expect_right<T,U>(eith: Either<T,U>, reason: &str) -> U {
136145
match eith {
137146
Right(x) => x,
138-
Left(_) => fail!("either::unwrap_right Left")
147+
Left(_) => fail!(reason.to_owned())
139148
}
140149
}
141150

151+
/// Retrieves the value in the right branch. Fails if the either is Left.
152+
pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
153+
expect_right(eith, "either::unwrap_right Left")
154+
}
155+
142156
impl<T, U> Either<T, U> {
143157
#[inline]
144158
pub fn either<V>(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V {
@@ -157,9 +171,15 @@ impl<T, U> Either<T, U> {
157171
#[inline]
158172
pub fn is_right(&self) -> bool { is_right(self) }
159173

174+
#[inline]
175+
pub fn expect_left(self, reason: &str) -> T { expect_left(self, reason) }
176+
160177
#[inline]
161178
pub fn unwrap_left(self) -> T { unwrap_left(self) }
162179

180+
#[inline]
181+
pub fn expect_right(self, reason: &str) -> U { expect_right(self, reason) }
182+
163183
#[inline]
164184
pub fn unwrap_right(self) -> U { unwrap_right(self) }
165185
}

0 commit comments

Comments
 (0)