Using move-mode for spawn thunks to avoid race conditions.

This commit is contained in:
Eric Holk 2011-08-17 11:44:35 -07:00
parent 1d7ca9c189
commit 94260fb91d
16 changed files with 60 additions and 31 deletions

View file

@ -75,21 +75,22 @@ fn set_min_stack(stack_size : uint) {
rustrt::set_min_stack(stack_size);
}
fn _spawn(thunk : fn() -> ()) -> task {
fn _spawn(thunk : -fn() -> ()) -> task {
spawn(thunk)
}
fn spawn(thunk : fn() -> ()) -> task {
fn spawn(thunk : -fn() -> ()) -> task {
spawn_inner(thunk, none)
}
fn spawn_notify(thunk : fn() -> (), notify : _chan<task_notification>)
fn spawn_notify(thunk : -fn() -> (), notify : _chan<task_notification>)
-> task {
spawn_inner(thunk, some(notify))
}
// FIXME: make this a fn~ once those are supported.
fn spawn_inner(thunk : fn() -> (), notify : option<_chan<task_notification>>)
fn spawn_inner(thunk : -fn() -> (),
notify : option<_chan<task_notification>>)
-> task_id {
let id = rustrt::new_task();

View file

@ -336,13 +336,16 @@ fn run_test(test: &test_desc, to_task: &test_to_task) -> test_future {
// we've got to treat our test functions as unsafe pointers. This function
// only works with functions that don't contain closures.
fn default_test_to_task(f: &fn()) -> task_id {
/*
fn run_task(fptr: *mutable fn() ) {
configure_test_task();
// Run the test
(*fptr)()
}
let fptr = ptr::addr_of(f);
ret task::_spawn(bind run_task(fptr));
*/
//ret task::_spawn(bind run_task(fptr));
task::spawn(f)
}
// Call from within a test task to make sure it's set up correctly

View file

@ -7,7 +7,8 @@ import std::str;
fn f(n: uint) {
let i = 0u;
while i < n {
task::join_id(task::_spawn(bind g()));
let thunk = g;
task::join_id(task::spawn(thunk));
i += 1u;
}
}
@ -23,7 +24,7 @@ fn main(args: [str]) {
};
let i = 0u;
while i < n {
task::_spawn(bind f(n));
task::spawn(bind f(n));
i += 1u;
}
}

View file

@ -77,7 +77,7 @@ mod map_reduce {
fn start_mappers(ctrl: _chan<ctrl_proto>, inputs: &[str]) -> [task_id] {
let tasks = ~[];
for i: str in inputs {
tasks += ~[task::_spawn(bind map_task(ctrl, i))];
tasks += ~[task::spawn(bind map_task(ctrl, i))];
}
ret tasks;
}
@ -179,7 +179,7 @@ mod map_reduce {
// log_err "creating new reducer for " + k;
let p = mk_port();
tasks +=
~[task::_spawn(bind reduce_task(k, p.mk_chan()))];
~[task::spawn(bind reduce_task(k, p.mk_chan()))];
c = p.recv();
reducers.insert(k, c);
}

View file

@ -11,6 +11,7 @@ fn child() { assert (1 == 2); }
fn main() {
let p = mk_port::<int>();
task::_spawn(bind child());
let f = child;
task::_spawn(f);
let x = p.recv();
}

View file

@ -85,8 +85,9 @@ fn test_ptr() {
fn test_task() {
fn f() { }
let t1 = task::_spawn(bind f());
let t2 = task::_spawn(bind f());
let f1 = f, f2 = f;
let t1 = task::spawn(f1);
let t2 = task::spawn(f2);
assert t1 == t1;
assert t1 != t2;

View file

@ -13,4 +13,7 @@ fn yield_wrap() {
rustrt::task_yield();
}
fn main() { task::_spawn(bind yield_wrap()); }
fn main() {
let f = yield_wrap;
task::_spawn(f);
}

View file

@ -5,7 +5,8 @@ use std;
import std::task::*;
fn main() {
let other = _spawn(bind child());
let f = child;
let other = _spawn(f);
log_err "1";
yield();
join_id(other);

View file

@ -1,10 +1,15 @@
use std;
import std::task::_spawn;
import std::task::spawn;
import std::task::join_id;
fn main() { test00(); }
fn start() { log "Started / Finished task."; }
fn test00() { let t = _spawn(bind start()); join_id(t); log "Completing."; }
fn test00() {
let f = start;
let t = spawn(f);
join_id(t);
log "Completing.";
}

View file

@ -37,7 +37,7 @@ fn test00() {
let tasks = [];
while i < number_of_tasks {
i = i + 1;
tasks += [task::_spawn(bind test00_start(ch, i, number_of_messages))];
tasks += [task::spawn(bind test00_start(ch, i, number_of_messages))];
}
let sum: int = 0;
@ -96,7 +96,11 @@ fn test04_start() {
fn test04() {
log "Spawning lots of tasks.";
let i: int = 4;
while i > 0 { i = i - 1; task::_spawn(bind test04_start()); }
while i > 0 {
i = i - 1;
let f = test04_start;
task::spawn(f);
}
log "Finishing up.";
}
@ -111,7 +115,7 @@ fn test05_start(ch: _chan<int>) {
fn test05() {
let po = comm::mk_port();
let ch = po.mk_chan();
task::_spawn(bind test05_start(ch));
task::spawn(bind test05_start(ch));
let value: int;
value = po.recv();
value = po.recv();
@ -134,7 +138,7 @@ fn test06() {
let tasks = [];
while i < number_of_tasks {
i = i + 1; tasks += [task::_spawn(bind test06_start(i))]; }
i = i + 1; tasks += [task::spawn(bind test06_start(i))]; }
for t: task_id in tasks { task::join_id(t); }

View file

@ -14,8 +14,9 @@ fn main() {
let t1;
let t2;
t1 = task::_spawn(bind child());
t2 = task::_spawn(bind child());
let c1 = child, c2 = child;
t1 = task::_spawn(c1);
t2 = task::_spawn(c2);
assert (t1 == t1);
assert (t1 != t2);

View file

@ -24,12 +24,14 @@ fn supervisor() {
// Unsupervise this task so the process doesn't return a failure status as
// a result of the main task being killed.
task::unsupervise();
let t = task::_spawn(bind supervised());
let f = supervised;
let t = task::_spawn(supervised);
task::join_id(t);
}
fn main() {
let dom2 = task::_spawn(bind supervisor());
let f = supervisor;
let dom2 = task::_spawn(f);
task::join_id(dom2);
}

View file

@ -4,7 +4,8 @@ import std::task;
import std::task::*;
fn main() {
let other = task::_spawn(bind child());
let f = child;
let other = task::spawn(f);
log_err "1";
yield();
log_err "2";

View file

@ -4,7 +4,8 @@ import std::task;
import std::task::*;
fn main() {
let other = task::_spawn(bind child());
let c = child;
let other = task::spawn(c);
log_err "1"; yield();
join_id(other);
}

View file

@ -4,4 +4,4 @@ use std;
fn main() {
let i: int = 0;
while i < 100 { i = i + 1; log_err i; std::task::yield(); }
}
}

View file

@ -8,7 +8,8 @@ fn test_sleep() { task::sleep(1000000u); }
#[test]
fn test_unsupervise() {
fn f() { task::unsupervise(); fail; }
task::_spawn(bind f());
let foo = f;
task::_spawn(foo);
}
#[test]
@ -30,7 +31,8 @@ fn test_join() {
#[test]
fn test_lib_spawn() {
fn foo() { log_err "Hello, World!"; }
task::_spawn(foo);
let f = foo;
task::_spawn(f);
}
#[test]
@ -44,7 +46,8 @@ fn test_join_chan() {
fn winner() { }
let p = comm::mk_port::<task::task_notification>();
task::spawn_notify(bind winner(), p.mk_chan());
let f = winner;
task::spawn_notify(f, p.mk_chan());
let s = p.recv();
log_err "received task status message";
log_err s;
@ -59,7 +62,8 @@ fn test_join_chan_fail() {
fn failer() { task::unsupervise(); fail }
let p = comm::mk_port::<task::task_notification>();
task::spawn_notify(bind failer(), p.mk_chan());
let f = failer;
task::spawn_notify(f, p.mk_chan());
let s = p.recv();
log_err "received task status message";
log_err s;