std::rt: Change Thread interface to require an explicit join

Makes it more obvious what's going on
This commit is contained in:
Brian Anderson 2013-07-27 12:05:15 -07:00
parent 7265cc6530
commit 0144c83213
11 changed files with 69 additions and 45 deletions

View File

@ -674,10 +674,11 @@ mod test {
do run_in_newsched_task {
let (port, chan) = oneshot::<int>();
let port_cell = Cell::new(port);
let _thread = do spawntask_thread {
let thread = do spawntask_thread {
let _p = port_cell.take();
};
let _chan = chan;
thread.join();
}
}
}
@ -689,13 +690,15 @@ mod test {
let (port, chan) = oneshot::<int>();
let chan_cell = Cell::new(chan);
let port_cell = Cell::new(port);
let _thread1 = do spawntask_thread {
let thread1 = do spawntask_thread {
let _p = port_cell.take();
};
let _thread2 = do spawntask_thread {
let thread2 = do spawntask_thread {
let c = chan_cell.take();
c.send(1);
};
thread1.join();
thread2.join();
}
}
}
@ -707,19 +710,21 @@ mod test {
let (port, chan) = oneshot::<int>();
let chan_cell = Cell::new(chan);
let port_cell = Cell::new(port);
let _thread1 = do spawntask_thread {
let thread1 = do spawntask_thread {
let port_cell = Cell::new(port_cell.take());
let res = do spawntask_try {
port_cell.take().recv();
};
assert!(res.is_err());
};
let _thread2 = do spawntask_thread {
let thread2 = do spawntask_thread {
let chan_cell = Cell::new(chan_cell.take());
do spawntask {
chan_cell.take();
}
};
thread1.join();
thread2.join();
}
}
}
@ -731,12 +736,14 @@ mod test {
let (port, chan) = oneshot::<~int>();
let chan_cell = Cell::new(chan);
let port_cell = Cell::new(port);
let _thread1 = do spawntask_thread {
let thread1 = do spawntask_thread {
chan_cell.take().send(~10);
};
let _thread2 = do spawntask_thread {
let thread2 = do spawntask_thread {
assert!(port_cell.take().recv() == ~10);
};
thread1.join();
thread2.join();
}
}
}

View File

@ -343,7 +343,9 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
}
// Wait for schedulers
{ let _threads = threads; }
for threads.consume_iter().advance() |thread| {
thread.join();
}
// Return the exit code
unsafe {

View File

@ -901,10 +901,8 @@ mod test {
sched.run();
};
// wait for the end
let _thread1 = normal_thread;
let _thread2 = special_thread;
normal_thread.join();
special_thread.join();
}
}
@ -1074,16 +1072,19 @@ mod test {
sched2.enqueue_task(task2);
let sched1_cell = Cell::new(sched1);
let _thread1 = do Thread::start {
let thread1 = do Thread::start {
let sched1 = sched1_cell.take();
sched1.run();
};
let sched2_cell = Cell::new(sched2);
let _thread2 = do Thread::start {
let thread2 = do Thread::start {
let sched2 = sched2_cell.take();
sched2.run();
};
thread1.join();
thread2.join();
}
}

View File

@ -125,7 +125,9 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
}
// Wait for schedulers
let _threads = threads;
for threads.consume_iter().advance() |thread| {
thread.join();
}
}
}

View File

@ -16,7 +16,8 @@ type raw_thread = libc::c_void;
pub struct Thread {
main: ~fn(),
raw_thread: *raw_thread
raw_thread: *raw_thread,
joined: bool
}
impl Thread {
@ -27,18 +28,28 @@ impl Thread {
let raw = substart(&main);
Thread {
main: main,
raw_thread: raw
raw_thread: raw,
joined: false
}
}
pub fn join(self) {
assert!(!self.joined);
let mut this = self;
unsafe { rust_raw_thread_join(this.raw_thread); }
this.joined = true;
}
}
impl Drop for Thread {
fn drop(&self) {
unsafe { rust_raw_thread_join_delete(self.raw_thread) }
assert!(self.joined);
unsafe { rust_raw_thread_delete(self.raw_thread) }
}
}
extern {
pub unsafe fn rust_raw_thread_start(f: &(~fn())) -> *raw_thread;
pub unsafe fn rust_raw_thread_join_delete(thread: *raw_thread);
pub unsafe fn rust_raw_thread_join(thread: *raw_thread);
pub unsafe fn rust_raw_thread_delete(thread: *raw_thread);
}

View File

@ -94,12 +94,13 @@ mod test {
let mut loop_ = Loop::new();
let watcher = AsyncWatcher::new(&mut loop_, |w, _| w.close(||()) );
let watcher_cell = Cell::new(watcher);
let _thread = do Thread::start {
let thread = do Thread::start {
let mut watcher = watcher_cell.take();
watcher.send();
};
loop_.run();
loop_.close();
thread.join();
}
}
}

View File

@ -715,7 +715,7 @@ mod test {
}
}
let _client_thread = do Thread::start {
let client_thread = do Thread::start {
rtdebug!("starting client thread");
let mut loop_ = Loop::new();
let mut tcp_watcher = { TcpWatcher::new(&mut loop_) };
@ -739,6 +739,7 @@ mod test {
let mut loop_ = loop_;
loop_.run();
loop_.close();
client_thread.join();
}
}
@ -790,7 +791,7 @@ mod test {
}
}
let _client_thread = do Thread::start {
let client_thread = do Thread::start {
rtdebug!("starting client thread");
let mut loop_ = Loop::new();
let mut tcp_watcher = { TcpWatcher::new(&mut loop_) };
@ -814,6 +815,7 @@ mod test {
let mut loop_ = loop_;
loop_.run();
loop_.close();
client_thread.join();
}
}
@ -855,7 +857,7 @@ mod test {
server.close(||{});
}
do Thread::start {
let thread = do Thread::start {
let mut loop_ = Loop::new();
let mut client = UdpWatcher::new(&loop_);
assert!(client.bind(client_addr).is_ok());
@ -873,6 +875,7 @@ mod test {
loop_.run();
loop_.close();
thread.join();
}
}
@ -914,7 +917,7 @@ mod test {
server.close(||{});
}
do Thread::start {
let thread = do Thread::start {
let mut loop_ = Loop::new();
let mut client = UdpWatcher::new(&loop_);
assert!(client.bind(client_addr).is_ok());
@ -932,6 +935,7 @@ mod test {
loop_.run();
loop_.close();
thread.join();
}
}
}

View File

@ -222,11 +222,12 @@ mod test_remote {
};
remote_cell.put_back(remote);
}
let _thread = do Thread::start {
let thread = do Thread::start {
remote_cell.take().fire();
};
assert!(tube.recv() == 1);
thread.join();
}
}
}

View File

@ -12,7 +12,6 @@
use comm::{GenericChan, GenericPort};
use comm;
use libc;
use prelude::*;
use task;
@ -37,18 +36,16 @@ The executing thread has no access to a task pointer and will be using
a normal large stack.
*/
pub fn run_in_bare_thread(f: ~fn()) {
use cell::Cell;
use rt::thread::Thread;
let f_cell = Cell::new(f);
let (port, chan) = comm::stream();
// FIXME #4525: Unfortunate that this creates an extra scheduler but it's
// necessary since rust_raw_thread_join_delete is blocking
// necessary since rust_raw_thread_join is blocking
do task::spawn_sched(task::SingleThreaded) {
unsafe {
let closure: &fn() = || {
f()
};
let thread = rust_raw_thread_start(&closure);
rust_raw_thread_join_delete(thread);
chan.send(());
}
Thread::start(f_cell.take()).join();
chan.send(());
}
port.recv();
}
@ -70,14 +67,6 @@ fn test_run_in_bare_thread_exchange() {
}
}
#[allow(non_camel_case_types)] // runtime type
pub type raw_thread = libc::c_void;
extern {
fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread;
fn rust_raw_thread_join_delete(thread: *raw_thread);
}
/// Changes the current working directory to the specified
/// path while acquiring a global lock, then calls `action`.

View File

@ -751,9 +751,14 @@ rust_raw_thread_start(fn_env_pair *fn) {
}
extern "C" void
rust_raw_thread_join_delete(raw_thread *thread) {
rust_raw_thread_join(raw_thread *thread) {
assert(thread);
thread->join();
}
extern "C" void
rust_raw_thread_delete(raw_thread *thread) {
assert(thread);
delete thread;
}

View File

@ -211,7 +211,8 @@ linenoiseHistorySetMaxLen
linenoiseHistorySave
linenoiseHistoryLoad
rust_raw_thread_start
rust_raw_thread_join_delete
rust_raw_thread_join
rust_raw_thread_delete
rust_get_rt_tls_key
swap_registers
rust_readdir