mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
rollup merge of #20615: aturon/stab-2-thread
This commit takes a first pass at stabilizing `std::thread`: * It removes the `detach` method in favor of two constructors -- `spawn` for detached threads, `scoped` for "scoped" (i.e., must-join) threads. This addresses some of the surprise/frustrating debug sessions with the previous API, in which `spawn` produced a guard that on destruction joined the thread (unless `detach` was called). The reason to have the division in part is that `Send` will soon not imply `'static`, which means that `scoped` thread creation can take a closure over *shared stack data* of the parent thread. On the other hand, this means that the parent must not pop the relevant stack frames while the child thread is running. The `JoinGuard` is used to prevent this from happening by joining on drop (if you have not already explicitly `join`ed.) The APIs around `scoped` are future-proofed for the `Send` changes by taking an additional lifetime parameter. With the current definition of `Send`, this is forced to be `'static`, but when `Send` changes these APIs will gain their full flexibility immediately. Threads that are `spawn`ed, on the other hand, are detached from the start and do not yield an RAII guard. The hope is that, by making `scoped` an explicit opt-in with a very suggestive name, it will be drastically less likely to be caught by a surprising deadlock due to an implicit join at the end of a scope. * The module itself is marked stable. * Existing methods other than `spawn` and `scoped` are marked stable. The migration path is: ```rust Thread::spawn(f).detached() ``` becomes ```rust Thread::spawn(f) ``` while ```rust let res = Thread::spawn(f); res.join() ``` becomes ```rust let res = Thread::scoped(f); res.join() ``` [breaking-change]
This commit is contained in:
commit
36f5d122b8
@ -447,7 +447,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
|
|||||||
loop {
|
loop {
|
||||||
//waiting 1 second for gdbserver start
|
//waiting 1 second for gdbserver start
|
||||||
timer::sleep(Duration::milliseconds(1000));
|
timer::sleep(Duration::milliseconds(1000));
|
||||||
let result = Thread::spawn(move || {
|
let result = Thread::scoped(move || {
|
||||||
tcp::TcpStream::connect("127.0.0.1:5039").unwrap();
|
tcp::TcpStream::connect("127.0.0.1:5039").unwrap();
|
||||||
}).join();
|
}).join();
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
|
@ -395,7 +395,7 @@ fn main() {
|
|||||||
for _ in range(0u, 10u) {
|
for _ in range(0u, 10u) {
|
||||||
Thread::spawn(move || {
|
Thread::spawn(move || {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -405,8 +405,7 @@ This program creates ten threads, who all print `Hello, world!`. The
|
|||||||
double bars `||`. (The `move` keyword indicates that the closure takes
|
double bars `||`. (The `move` keyword indicates that the closure takes
|
||||||
ownership of any data it uses; we'll have more on the significance of
|
ownership of any data it uses; we'll have more on the significance of
|
||||||
this shortly.) This closure is executed in a new thread created by
|
this shortly.) This closure is executed in a new thread created by
|
||||||
`spawn`. The `detach` method means that the child thread is allowed to
|
`spawn`.
|
||||||
outlive its parent.
|
|
||||||
|
|
||||||
One common form of problem in concurrent programs is a 'data race.'
|
One common form of problem in concurrent programs is a 'data race.'
|
||||||
This occurs when two different threads attempt to access the same
|
This occurs when two different threads attempt to access the same
|
||||||
@ -429,7 +428,7 @@ fn main() {
|
|||||||
for i in range(0u, 3u) {
|
for i in range(0u, 3u) {
|
||||||
Thread::spawn(move || {
|
Thread::spawn(move || {
|
||||||
for j in range(0, 3) { numbers[j] += 1 }
|
for j in range(0, 3) { numbers[j] += 1 }
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -488,7 +487,7 @@ fn main() {
|
|||||||
(*array)[i] += 1;
|
(*array)[i] += 1;
|
||||||
|
|
||||||
println!("numbers[{}] is {}", i, (*array)[i]);
|
println!("numbers[{}] is {}", i, (*array)[i]);
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Thread::spawn(move || {
|
//! Thread::spawn(move || {
|
||||||
//! println!("{}", five);
|
//! println!("{}", five);
|
||||||
//! }).detach();
|
//! });
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@ -63,7 +63,7 @@
|
|||||||
//! *number += 1;
|
//! *number += 1;
|
||||||
//!
|
//!
|
||||||
//! println!("{}", *number); // prints 6
|
//! println!("{}", *number); // prints 6
|
||||||
//! }).detach();
|
//! });
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ use heap::deallocate;
|
|||||||
/// let local_numbers = child_numbers.as_slice();
|
/// let local_numbers = child_numbers.as_slice();
|
||||||
///
|
///
|
||||||
/// // Work with the local numbers
|
/// // Work with the local numbers
|
||||||
/// }).detach();
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -924,7 +924,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_send() {
|
fn test_send() {
|
||||||
let n = list_from(&[1i,2,3]);
|
let n = list_from(&[1i,2,3]);
|
||||||
Thread::spawn(move || {
|
Thread::scoped(move || {
|
||||||
check_links(&n);
|
check_links(&n);
|
||||||
let a: &[_] = &[&1,&2,&3];
|
let a: &[_] = &[&1,&2,&3];
|
||||||
assert_eq!(a, n.iter().collect::<Vec<&int>>());
|
assert_eq!(a, n.iter().collect::<Vec<&int>>());
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
//! let spinlock_clone = spinlock.clone();
|
//! let spinlock_clone = spinlock.clone();
|
||||||
//! Thread::spawn(move|| {
|
//! Thread::spawn(move|| {
|
||||||
//! spinlock_clone.store(0, Ordering::SeqCst);
|
//! spinlock_clone.store(0, Ordering::SeqCst);
|
||||||
//! }).detach();
|
//! });
|
||||||
//!
|
//!
|
||||||
//! // Wait for the other task to release the lock
|
//! // Wait for the other task to release the lock
|
||||||
//! while spinlock.load(Ordering::SeqCst) != 0 {}
|
//! while spinlock.load(Ordering::SeqCst) != 0 {}
|
||||||
|
@ -543,7 +543,7 @@ pub fn monitor<F:FnOnce()+Send>(f: F) {
|
|||||||
cfg = cfg.stack_size(STACK_SIZE);
|
cfg = cfg.stack_size(STACK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
match cfg.spawn(move || { std::io::stdio::set_stderr(box w); f() }).join() {
|
match cfg.scoped(move || { std::io::stdio::set_stderr(box w); f() }).join() {
|
||||||
Ok(()) => { /* fallthrough */ }
|
Ok(()) => { /* fallthrough */ }
|
||||||
Err(value) => {
|
Err(value) => {
|
||||||
// Thread panicked without emitting a fatal diagnostic
|
// Thread panicked without emitting a fatal diagnostic
|
||||||
|
@ -928,7 +928,7 @@ fn run_work_multithreaded(sess: &Session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
tx.take().unwrap().send(()).unwrap();
|
tx.take().unwrap().send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut panicked = false;
|
let mut panicked = false;
|
||||||
|
@ -103,7 +103,7 @@ struct Output {
|
|||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
static STACK_SIZE: uint = 32000000; // 32MB
|
static STACK_SIZE: uint = 32000000; // 32MB
|
||||||
let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
|
let res = std::thread::Builder::new().stack_size(STACK_SIZE).scoped(move || {
|
||||||
main_args(std::os::args().as_slice())
|
main_args(std::os::args().as_slice())
|
||||||
}).join();
|
}).join();
|
||||||
std::os::set_exit_status(res.map_err(|_| ()).unwrap());
|
std::os::set_exit_status(res.map_err(|_| ()).unwrap());
|
||||||
@ -345,7 +345,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
|
|||||||
let cr = Path::new(cratefile);
|
let cr = Path::new(cratefile);
|
||||||
info!("starting to run rustc");
|
info!("starting to run rustc");
|
||||||
|
|
||||||
let (mut krate, analysis) = std::thread::Thread::spawn(move |:| {
|
let (mut krate, analysis) = std::thread::Thread::scoped(move |:| {
|
||||||
let cr = cr;
|
let cr = cr;
|
||||||
core::run_core(paths, cfgs, externs, &cr, triple)
|
core::run_core(paths, cfgs, externs, &cr, triple)
|
||||||
}).join().map_err(|_| "rustc failed").unwrap();
|
}).join().map_err(|_| "rustc failed").unwrap();
|
||||||
|
@ -157,7 +157,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
|||||||
None => box io::stderr() as Box<Writer>,
|
None => box io::stderr() as Box<Writer>,
|
||||||
};
|
};
|
||||||
io::util::copy(&mut p, &mut err).unwrap();
|
io::util::copy(&mut p, &mut err).unwrap();
|
||||||
}).detach();
|
});
|
||||||
let emitter = diagnostic::EmitterWriter::new(box w2, None);
|
let emitter = diagnostic::EmitterWriter::new(box w2, None);
|
||||||
|
|
||||||
// Compile the code
|
// Compile the code
|
||||||
|
@ -173,7 +173,7 @@ mod test {
|
|||||||
tx.send(vec![3u8, 4u8]).unwrap();
|
tx.send(vec![3u8, 4u8]).unwrap();
|
||||||
tx.send(vec![5u8, 6u8]).unwrap();
|
tx.send(vec![5u8, 6u8]).unwrap();
|
||||||
tx.send(vec![7u8, 8u8]).unwrap();
|
tx.send(vec![7u8, 8u8]).unwrap();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut reader = ChanReader::new(rx);
|
let mut reader = ChanReader::new(rx);
|
||||||
let mut buf = [0u8; 3];
|
let mut buf = [0u8; 3];
|
||||||
@ -216,7 +216,7 @@ mod test {
|
|||||||
tx.send(b"rld\nhow ".to_vec()).unwrap();
|
tx.send(b"rld\nhow ".to_vec()).unwrap();
|
||||||
tx.send(b"are you?".to_vec()).unwrap();
|
tx.send(b"are you?".to_vec()).unwrap();
|
||||||
tx.send(b"".to_vec()).unwrap();
|
tx.send(b"".to_vec()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut reader = ChanReader::new(rx);
|
let mut reader = ChanReader::new(rx);
|
||||||
|
|
||||||
@ -235,7 +235,7 @@ mod test {
|
|||||||
writer.write_be_u32(42).unwrap();
|
writer.write_be_u32(42).unwrap();
|
||||||
|
|
||||||
let wanted = vec![0u8, 0u8, 0u8, 42u8];
|
let wanted = vec![0u8, 0u8, 0u8, 42u8];
|
||||||
let got = match Thread::spawn(move|| { rx.recv().unwrap() }).join() {
|
let got = match Thread::scoped(move|| { rx.recv().unwrap() }).join() {
|
||||||
Ok(got) => got,
|
Ok(got) => got,
|
||||||
Err(_) => panic!(),
|
Err(_) => panic!(),
|
||||||
};
|
};
|
||||||
|
@ -120,10 +120,12 @@
|
|||||||
//! for stream in acceptor.incoming() {
|
//! for stream in acceptor.incoming() {
|
||||||
//! match stream {
|
//! match stream {
|
||||||
//! Err(e) => { /* connection failed */ }
|
//! Err(e) => { /* connection failed */ }
|
||||||
//! Ok(stream) => Thread::spawn(move|| {
|
//! Ok(stream) => {
|
||||||
//! // connection succeeded
|
//! Thread::spawn(move|| {
|
||||||
//! handle_client(stream)
|
//! // connection succeeded
|
||||||
//! }).detach()
|
//! handle_client(stream)
|
||||||
|
//! });
|
||||||
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -608,7 +608,7 @@ mod tests {
|
|||||||
let mut a = a;
|
let mut a = a;
|
||||||
let _s = a.accept().unwrap();
|
let _s = a.accept().unwrap();
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut b = [0];
|
let mut b = [0];
|
||||||
let mut s = UnixStream::connect(&addr).unwrap();
|
let mut s = UnixStream::connect(&addr).unwrap();
|
||||||
@ -645,7 +645,7 @@ mod tests {
|
|||||||
let mut a = a;
|
let mut a = a;
|
||||||
let _s = a.accept().unwrap();
|
let _s = a.accept().unwrap();
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = UnixStream::connect(&addr).unwrap();
|
let mut s = UnixStream::connect(&addr).unwrap();
|
||||||
let s2 = s.clone();
|
let s2 = s.clone();
|
||||||
@ -672,7 +672,7 @@ mod tests {
|
|||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
assert!(s.write(&[0]).is_ok());
|
assert!(s.write(&[0]).is_ok());
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
s.set_timeout(Some(20));
|
s.set_timeout(Some(20));
|
||||||
@ -716,7 +716,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
s.set_read_timeout(Some(20));
|
s.set_read_timeout(Some(20));
|
||||||
@ -739,7 +739,7 @@ mod tests {
|
|||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
assert!(s.write(&[0]).is_ok());
|
assert!(s.write(&[0]).is_ok());
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
s.set_write_timeout(Some(20));
|
s.set_write_timeout(Some(20));
|
||||||
@ -766,7 +766,7 @@ mod tests {
|
|||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
assert!(s.write(&[0]).is_ok());
|
assert!(s.write(&[0]).is_ok());
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
let s2 = s.clone();
|
let s2 = s.clone();
|
||||||
|
@ -146,7 +146,7 @@ impl TcpStream {
|
|||||||
/// timer::sleep(Duration::seconds(1));
|
/// timer::sleep(Duration::seconds(1));
|
||||||
/// let mut stream = stream2;
|
/// let mut stream = stream2;
|
||||||
/// stream.close_read();
|
/// stream.close_read();
|
||||||
/// }).detach();
|
/// });
|
||||||
///
|
///
|
||||||
/// // wait for some data, will get canceled after one second
|
/// // wait for some data, will get canceled after one second
|
||||||
/// let mut buf = [0];
|
/// let mut buf = [0];
|
||||||
@ -295,10 +295,12 @@ impl sys_common::AsInner<TcpStreamImp> for TcpStream {
|
|||||||
/// for stream in acceptor.incoming() {
|
/// for stream in acceptor.incoming() {
|
||||||
/// match stream {
|
/// match stream {
|
||||||
/// Err(e) => { /* connection failed */ }
|
/// Err(e) => { /* connection failed */ }
|
||||||
/// Ok(stream) => Thread::spawn(move|| {
|
/// Ok(stream) => {
|
||||||
/// // connection succeeded
|
/// Thread::spawn(move|| {
|
||||||
/// handle_client(stream)
|
/// // connection succeeded
|
||||||
/// }).detach()
|
/// handle_client(stream)
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@ -432,7 +434,7 @@ impl TcpAcceptor {
|
|||||||
/// Err(e) => panic!("unexpected error: {}", e),
|
/// Err(e) => panic!("unexpected error: {}", e),
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }).detach();
|
/// });
|
||||||
///
|
///
|
||||||
/// # fn wait_for_sigint() {}
|
/// # fn wait_for_sigint() {}
|
||||||
/// // Now that our accept loop is running, wait for the program to be
|
/// // Now that our accept loop is running, wait for the program to be
|
||||||
@ -1186,7 +1188,7 @@ mod test {
|
|||||||
let mut a = a;
|
let mut a = a;
|
||||||
let _s = a.accept().unwrap();
|
let _s = a.accept().unwrap();
|
||||||
let _ = rx.recv().unwrap();
|
let _ = rx.recv().unwrap();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut b = [0];
|
let mut b = [0];
|
||||||
let mut s = TcpStream::connect(addr).unwrap();
|
let mut s = TcpStream::connect(addr).unwrap();
|
||||||
@ -1223,7 +1225,7 @@ mod test {
|
|||||||
let mut a = a;
|
let mut a = a;
|
||||||
let _s = a.accept().unwrap();
|
let _s = a.accept().unwrap();
|
||||||
let _ = rx.recv().unwrap();
|
let _ = rx.recv().unwrap();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = TcpStream::connect(addr).unwrap();
|
let mut s = TcpStream::connect(addr).unwrap();
|
||||||
let s2 = s.clone();
|
let s2 = s.clone();
|
||||||
@ -1250,7 +1252,7 @@ mod test {
|
|||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
assert!(s.write(&[0]).is_ok());
|
assert!(s.write(&[0]).is_ok());
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
s.set_timeout(Some(20));
|
s.set_timeout(Some(20));
|
||||||
@ -1289,7 +1291,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
s.set_read_timeout(Some(20));
|
s.set_read_timeout(Some(20));
|
||||||
@ -1312,7 +1314,7 @@ mod test {
|
|||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
assert!(s.write(&[0]).is_ok());
|
assert!(s.write(&[0]).is_ok());
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
s.set_write_timeout(Some(20));
|
s.set_write_timeout(Some(20));
|
||||||
@ -1340,7 +1342,7 @@ mod test {
|
|||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
assert_eq!(s.write(&[0]), Ok(()));
|
assert_eq!(s.write(&[0]), Ok(()));
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let mut s = a.accept().unwrap();
|
let mut s = a.accept().unwrap();
|
||||||
let s2 = s.clone();
|
let s2 = s.clone();
|
||||||
|
@ -720,7 +720,7 @@ impl Process {
|
|||||||
Thread::spawn(move |:| {
|
Thread::spawn(move |:| {
|
||||||
let mut stream = stream;
|
let mut stream = stream;
|
||||||
tx.send(stream.read_to_end()).unwrap();
|
tx.send(stream.read_to_end()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
None => tx.send(Ok(Vec::new())).unwrap()
|
None => tx.send(Ok(Vec::new())).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@ mod test {
|
|||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
let _ = timer_rx.recv();
|
let _ = timer_rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
// when we drop the TimerWatcher we're going to destroy the channel,
|
// when we drop the TimerWatcher we're going to destroy the channel,
|
||||||
// which must wake up the task on the other end
|
// which must wake up the task on the other end
|
||||||
@ -372,7 +372,7 @@ mod test {
|
|||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
let _ = timer_rx.recv();
|
let _ = timer_rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
timer.oneshot(Duration::milliseconds(1));
|
timer.oneshot(Duration::milliseconds(1));
|
||||||
}
|
}
|
||||||
@ -385,7 +385,7 @@ mod test {
|
|||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
let _ = timer_rx.recv();
|
let _ = timer_rx.recv();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
timer.sleep(Duration::milliseconds(1));
|
timer.sleep(Duration::milliseconds(1));
|
||||||
}
|
}
|
||||||
|
@ -303,8 +303,8 @@ macro_rules! try {
|
|||||||
/// # fn long_running_task() {}
|
/// # fn long_running_task() {}
|
||||||
/// # fn calculate_the_answer() -> int { 42i }
|
/// # fn calculate_the_answer() -> int { 42i }
|
||||||
///
|
///
|
||||||
/// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach();
|
/// Thread::spawn(move|| { long_running_task(); tx1.send(()).unwrap(); });
|
||||||
/// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach();
|
/// Thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
|
||||||
///
|
///
|
||||||
/// select! (
|
/// select! (
|
||||||
/// _ = rx1.recv() => println!("the long running task finished first"),
|
/// _ = rx1.recv() => println!("the long running task finished first"),
|
||||||
|
@ -510,17 +510,17 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_null_byte() {
|
fn test_null_byte() {
|
||||||
use thread::Thread;
|
use thread::Thread;
|
||||||
let result = Thread::spawn(move|| {
|
let result = Thread::scoped(move|| {
|
||||||
Path::new(b"foo/bar\0")
|
Path::new(b"foo/bar\0")
|
||||||
}).join();
|
}).join();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
||||||
let result = Thread::spawn(move|| {
|
let result = Thread::scoped(move|| {
|
||||||
Path::new("test").set_filename(b"f\0o")
|
Path::new("test").set_filename(b"f\0o")
|
||||||
}).join();
|
}).join();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
||||||
let result = Thread::spawn(move|| {
|
let result = Thread::scoped(move|| {
|
||||||
Path::new("test").push(b"f\0o");
|
Path::new("test").push(b"f\0o");
|
||||||
}).join();
|
}).join();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
@ -1298,17 +1298,17 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_null_byte() {
|
fn test_null_byte() {
|
||||||
use thread::Thread;
|
use thread::Thread;
|
||||||
let result = Thread::spawn(move|| {
|
let result = Thread::scoped(move|| {
|
||||||
Path::new(b"foo/bar\0")
|
Path::new(b"foo/bar\0")
|
||||||
}).join();
|
}).join();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
||||||
let result = Thread::spawn(move|| {
|
let result = Thread::scoped(move|| {
|
||||||
Path::new("test").set_filename(b"f\0o")
|
Path::new("test").set_filename(b"f\0o")
|
||||||
}).join();
|
}).join();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
||||||
let result = Thread::spawn(move || {
|
let result = Thread::scoped(move || {
|
||||||
Path::new("test").push(b"f\0o");
|
Path::new("test").push(b"f\0o");
|
||||||
}).join();
|
}).join();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
@ -394,7 +394,7 @@ mod test {
|
|||||||
r.fill_bytes(&mut v);
|
r.fill_bytes(&mut v);
|
||||||
Thread::yield_now();
|
Thread::yield_now();
|
||||||
}
|
}
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// start all the tasks
|
// start all the tasks
|
||||||
|
@ -26,7 +26,7 @@ use sync::{Mutex, Condvar};
|
|||||||
/// println!("before wait");
|
/// println!("before wait");
|
||||||
/// c.wait();
|
/// c.wait();
|
||||||
/// println!("after wait");
|
/// println!("after wait");
|
||||||
/// }).detach();
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable]
|
#[stable]
|
||||||
@ -126,7 +126,7 @@ mod tests {
|
|||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(c.wait().is_leader()).unwrap();
|
tx.send(c.wait().is_leader()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, all spawned tasks should be blocked,
|
// At this point, all spawned tasks should be blocked,
|
||||||
|
@ -48,7 +48,7 @@ use sync::{mutex, MutexGuard};
|
|||||||
/// let mut started = lock.lock().unwrap();
|
/// let mut started = lock.lock().unwrap();
|
||||||
/// *started = true;
|
/// *started = true;
|
||||||
/// cvar.notify_one();
|
/// cvar.notify_one();
|
||||||
/// }).detach();
|
/// });
|
||||||
///
|
///
|
||||||
/// // wait for the thread to start up
|
/// // wait for the thread to start up
|
||||||
/// let &(ref lock, ref cvar) = &*pair;
|
/// let &(ref lock, ref cvar) = &*pair;
|
||||||
@ -338,7 +338,7 @@ mod tests {
|
|||||||
cnt = cond.wait(cnt).unwrap();
|
cnt = cond.wait(cnt).unwrap();
|
||||||
}
|
}
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
drop(tx);
|
drop(tx);
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ impl<A:Send> Future<A> {
|
|||||||
Thread::spawn(move |:| {
|
Thread::spawn(move |:| {
|
||||||
// Don't panic if the other end has hung up
|
// Don't panic if the other end has hung up
|
||||||
let _ = tx.send(blk());
|
let _ = tx.send(blk());
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
Future::from_receiver(rx)
|
Future::from_receiver(rx)
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
//! let (tx, rx) = channel();
|
//! let (tx, rx) = channel();
|
||||||
//! Thread::spawn(move|| {
|
//! Thread::spawn(move|| {
|
||||||
//! tx.send(10i).unwrap();
|
//! tx.send(10i).unwrap();
|
||||||
//! }).detach();
|
//! });
|
||||||
//! assert_eq!(rx.recv().unwrap(), 10i);
|
//! assert_eq!(rx.recv().unwrap(), 10i);
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@ -78,7 +78,7 @@
|
|||||||
//! let tx = tx.clone();
|
//! let tx = tx.clone();
|
||||||
//! Thread::spawn(move|| {
|
//! Thread::spawn(move|| {
|
||||||
//! tx.send(i).unwrap();
|
//! tx.send(i).unwrap();
|
||||||
//! }).detach()
|
//! });
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! for _ in range(0i, 10i) {
|
//! for _ in range(0i, 10i) {
|
||||||
@ -109,7 +109,7 @@
|
|||||||
//! Thread::spawn(move|| {
|
//! Thread::spawn(move|| {
|
||||||
//! // This will wait for the parent task to start receiving
|
//! // This will wait for the parent task to start receiving
|
||||||
//! tx.send(53).unwrap();
|
//! tx.send(53).unwrap();
|
||||||
//! }).detach();
|
//! });
|
||||||
//! rx.recv().unwrap();
|
//! rx.recv().unwrap();
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@ -476,7 +476,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
|
|||||||
/// Thread::spawn(move|| {
|
/// Thread::spawn(move|| {
|
||||||
/// # fn expensive_computation() {}
|
/// # fn expensive_computation() {}
|
||||||
/// tx.send(expensive_computation()).unwrap();
|
/// tx.send(expensive_computation()).unwrap();
|
||||||
/// }).detach();
|
/// });
|
||||||
///
|
///
|
||||||
/// // Do some useful work for awhile
|
/// // Do some useful work for awhile
|
||||||
///
|
///
|
||||||
@ -518,7 +518,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
|
|||||||
/// Thread::spawn(move|| {
|
/// Thread::spawn(move|| {
|
||||||
/// // this will block until the previous message has been received
|
/// // this will block until the previous message has been received
|
||||||
/// tx.send(2i).unwrap();
|
/// tx.send(2i).unwrap();
|
||||||
/// }).detach();
|
/// });
|
||||||
///
|
///
|
||||||
/// assert_eq!(rx.recv().unwrap(), 1i);
|
/// assert_eq!(rx.recv().unwrap(), 1i);
|
||||||
/// assert_eq!(rx.recv().unwrap(), 2i);
|
/// assert_eq!(rx.recv().unwrap(), 2i);
|
||||||
@ -1144,7 +1144,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn stress() {
|
fn stress() {
|
||||||
let (tx, rx) = channel::<int>();
|
let (tx, rx) = channel::<int>();
|
||||||
let t = Thread::spawn(move|| {
|
let t = Thread::scoped(move|| {
|
||||||
for _ in range(0u, 10000) { tx.send(1i).unwrap(); }
|
for _ in range(0u, 10000) { tx.send(1i).unwrap(); }
|
||||||
});
|
});
|
||||||
for _ in range(0u, 10000) {
|
for _ in range(0u, 10000) {
|
||||||
@ -1159,7 +1159,7 @@ mod test {
|
|||||||
static NTHREADS: uint = 8;
|
static NTHREADS: uint = 8;
|
||||||
let (tx, rx) = channel::<int>();
|
let (tx, rx) = channel::<int>();
|
||||||
|
|
||||||
let t = Thread::spawn(move|| {
|
let t = Thread::scoped(move|| {
|
||||||
for _ in range(0, AMT * NTHREADS) {
|
for _ in range(0, AMT * NTHREADS) {
|
||||||
assert_eq!(rx.recv().unwrap(), 1);
|
assert_eq!(rx.recv().unwrap(), 1);
|
||||||
}
|
}
|
||||||
@ -1173,7 +1173,7 @@ mod test {
|
|||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
for _ in range(0, AMT) { tx.send(1).unwrap(); }
|
for _ in range(0, AMT) { tx.send(1).unwrap(); }
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
drop(tx);
|
drop(tx);
|
||||||
t.join().ok().unwrap();
|
t.join().ok().unwrap();
|
||||||
@ -1183,14 +1183,14 @@ mod test {
|
|||||||
fn send_from_outside_runtime() {
|
fn send_from_outside_runtime() {
|
||||||
let (tx1, rx1) = channel::<()>();
|
let (tx1, rx1) = channel::<()>();
|
||||||
let (tx2, rx2) = channel::<int>();
|
let (tx2, rx2) = channel::<int>();
|
||||||
let t1 = Thread::spawn(move|| {
|
let t1 = Thread::scoped(move|| {
|
||||||
tx1.send(()).unwrap();
|
tx1.send(()).unwrap();
|
||||||
for _ in range(0i, 40) {
|
for _ in range(0i, 40) {
|
||||||
assert_eq!(rx2.recv().unwrap(), 1);
|
assert_eq!(rx2.recv().unwrap(), 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
rx1.recv().unwrap();
|
rx1.recv().unwrap();
|
||||||
let t2 = Thread::spawn(move|| {
|
let t2 = Thread::scoped(move|| {
|
||||||
for _ in range(0i, 40) {
|
for _ in range(0i, 40) {
|
||||||
tx2.send(1).unwrap();
|
tx2.send(1).unwrap();
|
||||||
}
|
}
|
||||||
@ -1202,7 +1202,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn recv_from_outside_runtime() {
|
fn recv_from_outside_runtime() {
|
||||||
let (tx, rx) = channel::<int>();
|
let (tx, rx) = channel::<int>();
|
||||||
let t = Thread::spawn(move|| {
|
let t = Thread::scoped(move|| {
|
||||||
for _ in range(0i, 40) {
|
for _ in range(0i, 40) {
|
||||||
assert_eq!(rx.recv().unwrap(), 1);
|
assert_eq!(rx.recv().unwrap(), 1);
|
||||||
}
|
}
|
||||||
@ -1217,11 +1217,11 @@ mod test {
|
|||||||
fn no_runtime() {
|
fn no_runtime() {
|
||||||
let (tx1, rx1) = channel::<int>();
|
let (tx1, rx1) = channel::<int>();
|
||||||
let (tx2, rx2) = channel::<int>();
|
let (tx2, rx2) = channel::<int>();
|
||||||
let t1 = Thread::spawn(move|| {
|
let t1 = Thread::scoped(move|| {
|
||||||
assert_eq!(rx1.recv().unwrap(), 1);
|
assert_eq!(rx1.recv().unwrap(), 1);
|
||||||
tx2.send(2).unwrap();
|
tx2.send(2).unwrap();
|
||||||
});
|
});
|
||||||
let t2 = Thread::spawn(move|| {
|
let t2 = Thread::scoped(move|| {
|
||||||
tx1.send(1).unwrap();
|
tx1.send(1).unwrap();
|
||||||
assert_eq!(rx2.recv().unwrap(), 2);
|
assert_eq!(rx2.recv().unwrap(), 2);
|
||||||
});
|
});
|
||||||
@ -1254,7 +1254,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn oneshot_single_thread_recv_chan_close() {
|
fn oneshot_single_thread_recv_chan_close() {
|
||||||
// Receiving on a closed chan will panic
|
// Receiving on a closed chan will panic
|
||||||
let res = Thread::spawn(move|| {
|
let res = Thread::scoped(move|| {
|
||||||
let (tx, rx) = channel::<int>();
|
let (tx, rx) = channel::<int>();
|
||||||
drop(tx);
|
drop(tx);
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
@ -1336,7 +1336,7 @@ mod test {
|
|||||||
let _t = Thread::spawn(move|| {
|
let _t = Thread::spawn(move|| {
|
||||||
drop(tx);
|
drop(tx);
|
||||||
});
|
});
|
||||||
let res = Thread::spawn(move|| {
|
let res = Thread::scoped(move|| {
|
||||||
assert!(rx.recv().unwrap() == box 10);
|
assert!(rx.recv().unwrap() == box 10);
|
||||||
}).join();
|
}).join();
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
@ -1360,7 +1360,7 @@ mod test {
|
|||||||
let _t = Thread::spawn(move|| {
|
let _t = Thread::spawn(move|| {
|
||||||
drop(rx);
|
drop(rx);
|
||||||
});
|
});
|
||||||
let _ = Thread::spawn(move|| {
|
let _ = Thread::scoped(move|| {
|
||||||
tx.send(1).unwrap();
|
tx.send(1).unwrap();
|
||||||
}).join();
|
}).join();
|
||||||
}
|
}
|
||||||
@ -1371,15 +1371,15 @@ mod test {
|
|||||||
for _ in range(0, stress_factor()) {
|
for _ in range(0, stress_factor()) {
|
||||||
let (tx, rx) = channel::<int>();
|
let (tx, rx) = channel::<int>();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
let res = Thread::spawn(move|| {
|
let res = Thread::scoped(move|| {
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
}).join();
|
}).join();
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
}).detach();
|
});
|
||||||
let _t = Thread::spawn(move|| {
|
let _t = Thread::spawn(move|| {
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
drop(tx);
|
drop(tx);
|
||||||
}).detach();
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1409,7 +1409,7 @@ mod test {
|
|||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(box i).unwrap();
|
tx.send(box i).unwrap();
|
||||||
send(tx, i + 1);
|
send(tx, i + 1);
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv(rx: Receiver<Box<int>>, i: int) {
|
fn recv(rx: Receiver<Box<int>>, i: int) {
|
||||||
@ -1418,7 +1418,7 @@ mod test {
|
|||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
assert!(rx.recv().unwrap() == box i);
|
assert!(rx.recv().unwrap() == box i);
|
||||||
recv(rx, i + 1);
|
recv(rx, i + 1);
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1439,7 +1439,7 @@ mod test {
|
|||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in range(0, total) {
|
for _ in range(0, total) {
|
||||||
@ -1644,7 +1644,7 @@ mod sync_tests {
|
|||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(1).unwrap();
|
tx.send(1).unwrap();
|
||||||
tx.send(1).unwrap();
|
tx.send(1).unwrap();
|
||||||
}).detach();
|
});
|
||||||
while rx.recv().is_ok() {}
|
while rx.recv().is_ok() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1653,7 +1653,7 @@ mod sync_tests {
|
|||||||
let (tx, rx) = sync_channel::<int>(0);
|
let (tx, rx) = sync_channel::<int>(0);
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
for _ in range(0u, 10000) { tx.send(1).unwrap(); }
|
for _ in range(0u, 10000) { tx.send(1).unwrap(); }
|
||||||
}).detach();
|
});
|
||||||
for _ in range(0u, 10000) {
|
for _ in range(0u, 10000) {
|
||||||
assert_eq!(rx.recv().unwrap(), 1);
|
assert_eq!(rx.recv().unwrap(), 1);
|
||||||
}
|
}
|
||||||
@ -1675,13 +1675,13 @@ mod sync_tests {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
dtx.send(()).unwrap();
|
dtx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
for _ in range(0, NTHREADS) {
|
for _ in range(0, NTHREADS) {
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
for _ in range(0, AMT) { tx.send(1).unwrap(); }
|
for _ in range(0, AMT) { tx.send(1).unwrap(); }
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
drop(tx);
|
drop(tx);
|
||||||
drx.recv().unwrap();
|
drx.recv().unwrap();
|
||||||
@ -1712,7 +1712,7 @@ mod sync_tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn oneshot_single_thread_recv_chan_close() {
|
fn oneshot_single_thread_recv_chan_close() {
|
||||||
// Receiving on a closed chan will panic
|
// Receiving on a closed chan will panic
|
||||||
let res = Thread::spawn(move|| {
|
let res = Thread::scoped(move|| {
|
||||||
let (tx, rx) = sync_channel::<int>(0);
|
let (tx, rx) = sync_channel::<int>(0);
|
||||||
drop(tx);
|
drop(tx);
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
@ -1800,7 +1800,7 @@ mod sync_tests {
|
|||||||
let _t = Thread::spawn(move|| {
|
let _t = Thread::spawn(move|| {
|
||||||
drop(tx);
|
drop(tx);
|
||||||
});
|
});
|
||||||
let res = Thread::spawn(move|| {
|
let res = Thread::scoped(move|| {
|
||||||
assert!(rx.recv().unwrap() == box 10);
|
assert!(rx.recv().unwrap() == box 10);
|
||||||
}).join();
|
}).join();
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
@ -1824,7 +1824,7 @@ mod sync_tests {
|
|||||||
let _t = Thread::spawn(move|| {
|
let _t = Thread::spawn(move|| {
|
||||||
drop(rx);
|
drop(rx);
|
||||||
});
|
});
|
||||||
let _ = Thread::spawn(move || {
|
let _ = Thread::scoped(move || {
|
||||||
tx.send(1).unwrap();
|
tx.send(1).unwrap();
|
||||||
}).join();
|
}).join();
|
||||||
}
|
}
|
||||||
@ -1835,7 +1835,7 @@ mod sync_tests {
|
|||||||
for _ in range(0, stress_factor()) {
|
for _ in range(0, stress_factor()) {
|
||||||
let (tx, rx) = sync_channel::<int>(0);
|
let (tx, rx) = sync_channel::<int>(0);
|
||||||
let _t = Thread::spawn(move|| {
|
let _t = Thread::spawn(move|| {
|
||||||
let res = Thread::spawn(move|| {
|
let res = Thread::scoped(move|| {
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
}).join();
|
}).join();
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
@ -1843,7 +1843,7 @@ mod sync_tests {
|
|||||||
let _t = Thread::spawn(move|| {
|
let _t = Thread::spawn(move|| {
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
drop(tx);
|
drop(tx);
|
||||||
}).detach();
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1873,7 +1873,7 @@ mod sync_tests {
|
|||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(box i).unwrap();
|
tx.send(box i).unwrap();
|
||||||
send(tx, i + 1);
|
send(tx, i + 1);
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv(rx: Receiver<Box<int>>, i: int) {
|
fn recv(rx: Receiver<Box<int>>, i: int) {
|
||||||
@ -1882,7 +1882,7 @@ mod sync_tests {
|
|||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
assert!(rx.recv().unwrap() == box i);
|
assert!(rx.recv().unwrap() == box i);
|
||||||
recv(rx, i + 1);
|
recv(rx, i + 1);
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1903,7 +1903,7 @@ mod sync_tests {
|
|||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in range(0, total) {
|
for _ in range(0, total) {
|
||||||
|
@ -188,7 +188,7 @@ mod tests {
|
|||||||
q.push(i);
|
q.push(i);
|
||||||
}
|
}
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
|
@ -75,7 +75,7 @@ use sys_common::mutex as sys;
|
|||||||
/// tx.send(()).unwrap();
|
/// tx.send(()).unwrap();
|
||||||
/// }
|
/// }
|
||||||
/// // the lock is unlocked here when `data` goes out of scope.
|
/// // the lock is unlocked here when `data` goes out of scope.
|
||||||
/// }).detach();
|
/// });
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// rx.recv().unwrap();
|
/// rx.recv().unwrap();
|
||||||
@ -90,7 +90,7 @@ use sys_common::mutex as sys;
|
|||||||
/// let lock = Arc::new(Mutex::new(0u));
|
/// let lock = Arc::new(Mutex::new(0u));
|
||||||
/// let lock2 = lock.clone();
|
/// let lock2 = lock.clone();
|
||||||
///
|
///
|
||||||
/// let _ = Thread::spawn(move || -> () {
|
/// let _ = Thread::scoped(move || -> () {
|
||||||
/// // This thread will acquire the mutex first, unwrapping the result of
|
/// // This thread will acquire the mutex first, unwrapping the result of
|
||||||
/// // `lock` because the lock has not been poisoned.
|
/// // `lock` because the lock has not been poisoned.
|
||||||
/// let _lock = lock2.lock().unwrap();
|
/// let _lock = lock2.lock().unwrap();
|
||||||
@ -376,9 +376,9 @@ mod test {
|
|||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
for _ in range(0, K) {
|
for _ in range(0, K) {
|
||||||
let tx2 = tx.clone();
|
let tx2 = tx.clone();
|
||||||
Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach();
|
Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
|
||||||
let tx2 = tx.clone();
|
let tx2 = tx.clone();
|
||||||
Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach();
|
Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(tx);
|
drop(tx);
|
||||||
@ -453,7 +453,7 @@ mod test {
|
|||||||
fn test_mutex_arc_poison() {
|
fn test_mutex_arc_poison() {
|
||||||
let arc = Arc::new(Mutex::new(1i));
|
let arc = Arc::new(Mutex::new(1i));
|
||||||
let arc2 = arc.clone();
|
let arc2 = arc.clone();
|
||||||
let _ = Thread::spawn(move|| {
|
let _ = Thread::scoped(move|| {
|
||||||
let lock = arc2.lock().unwrap();
|
let lock = arc2.lock().unwrap();
|
||||||
assert_eq!(*lock, 2);
|
assert_eq!(*lock, 2);
|
||||||
}).join();
|
}).join();
|
||||||
@ -480,7 +480,7 @@ mod test {
|
|||||||
fn test_mutex_arc_access_in_unwind() {
|
fn test_mutex_arc_access_in_unwind() {
|
||||||
let arc = Arc::new(Mutex::new(1i));
|
let arc = Arc::new(Mutex::new(1i));
|
||||||
let arc2 = arc.clone();
|
let arc2 = arc.clone();
|
||||||
let _ = Thread::spawn(move|| -> () {
|
let _ = Thread::scoped(move|| -> () {
|
||||||
struct Unwinder {
|
struct Unwinder {
|
||||||
i: Arc<Mutex<int>>,
|
i: Arc<Mutex<int>>,
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ mod test {
|
|||||||
assert!(run);
|
assert!(run);
|
||||||
}
|
}
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -411,7 +411,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop(tx);
|
drop(tx);
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
drop(tx);
|
drop(tx);
|
||||||
let _ = rx.recv();
|
let _ = rx.recv();
|
||||||
@ -422,7 +422,7 @@ mod tests {
|
|||||||
fn test_rw_arc_poison_wr() {
|
fn test_rw_arc_poison_wr() {
|
||||||
let arc = Arc::new(RwLock::new(1i));
|
let arc = Arc::new(RwLock::new(1i));
|
||||||
let arc2 = arc.clone();
|
let arc2 = arc.clone();
|
||||||
let _: Result<uint, _> = Thread::spawn(move|| {
|
let _: Result<uint, _> = Thread::scoped(move|| {
|
||||||
let _lock = arc2.write().unwrap();
|
let _lock = arc2.write().unwrap();
|
||||||
panic!();
|
panic!();
|
||||||
}).join();
|
}).join();
|
||||||
@ -433,7 +433,7 @@ mod tests {
|
|||||||
fn test_rw_arc_poison_ww() {
|
fn test_rw_arc_poison_ww() {
|
||||||
let arc = Arc::new(RwLock::new(1i));
|
let arc = Arc::new(RwLock::new(1i));
|
||||||
let arc2 = arc.clone();
|
let arc2 = arc.clone();
|
||||||
let _: Result<uint, _> = Thread::spawn(move|| {
|
let _: Result<uint, _> = Thread::scoped(move|| {
|
||||||
let _lock = arc2.write().unwrap();
|
let _lock = arc2.write().unwrap();
|
||||||
panic!();
|
panic!();
|
||||||
}).join();
|
}).join();
|
||||||
@ -444,7 +444,7 @@ mod tests {
|
|||||||
fn test_rw_arc_no_poison_rr() {
|
fn test_rw_arc_no_poison_rr() {
|
||||||
let arc = Arc::new(RwLock::new(1i));
|
let arc = Arc::new(RwLock::new(1i));
|
||||||
let arc2 = arc.clone();
|
let arc2 = arc.clone();
|
||||||
let _: Result<uint, _> = Thread::spawn(move|| {
|
let _: Result<uint, _> = Thread::scoped(move|| {
|
||||||
let _lock = arc2.read().unwrap();
|
let _lock = arc2.read().unwrap();
|
||||||
panic!();
|
panic!();
|
||||||
}).join();
|
}).join();
|
||||||
@ -455,7 +455,7 @@ mod tests {
|
|||||||
fn test_rw_arc_no_poison_rw() {
|
fn test_rw_arc_no_poison_rw() {
|
||||||
let arc = Arc::new(RwLock::new(1i));
|
let arc = Arc::new(RwLock::new(1i));
|
||||||
let arc2 = arc.clone();
|
let arc2 = arc.clone();
|
||||||
let _: Result<uint, _> = Thread::spawn(move|| {
|
let _: Result<uint, _> = Thread::scoped(move|| {
|
||||||
let _lock = arc2.read().unwrap();
|
let _lock = arc2.read().unwrap();
|
||||||
panic!()
|
panic!()
|
||||||
}).join();
|
}).join();
|
||||||
@ -478,13 +478,13 @@ mod tests {
|
|||||||
*lock = tmp + 1;
|
*lock = tmp + 1;
|
||||||
}
|
}
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
// Readers try to catch the writer in the act
|
// Readers try to catch the writer in the act
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
for _ in range(0u, 5) {
|
for _ in range(0u, 5) {
|
||||||
let arc3 = arc.clone();
|
let arc3 = arc.clone();
|
||||||
children.push(Thread::spawn(move|| {
|
children.push(Thread::scoped(move|| {
|
||||||
let lock = arc3.read().unwrap();
|
let lock = arc3.read().unwrap();
|
||||||
assert!(*lock >= 0);
|
assert!(*lock >= 0);
|
||||||
}));
|
}));
|
||||||
@ -505,7 +505,7 @@ mod tests {
|
|||||||
fn test_rw_arc_access_in_unwind() {
|
fn test_rw_arc_access_in_unwind() {
|
||||||
let arc = Arc::new(RwLock::new(1i));
|
let arc = Arc::new(RwLock::new(1i));
|
||||||
let arc2 = arc.clone();
|
let arc2 = arc.clone();
|
||||||
let _ = Thread::spawn(move|| -> () {
|
let _ = Thread::scoped(move|| -> () {
|
||||||
struct Unwinder {
|
struct Unwinder {
|
||||||
i: Arc<RwLock<int>>,
|
i: Arc<RwLock<int>>,
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ mod tests {
|
|||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
drop(s2.access());
|
drop(s2.access());
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
rx.recv().unwrap(); // wait for child to come alive
|
rx.recv().unwrap(); // wait for child to come alive
|
||||||
}
|
}
|
||||||
rx.recv().unwrap(); // wait for child to be done
|
rx.recv().unwrap(); // wait for child to be done
|
||||||
|
@ -132,7 +132,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sentinel.cancel();
|
sentinel.cancel();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -99,7 +99,7 @@ impl<M: Send> Helper<M> {
|
|||||||
let _g = self.lock.lock().unwrap();
|
let _g = self.lock.lock().unwrap();
|
||||||
*self.shutdown.get() = true;
|
*self.shutdown.get() = true;
|
||||||
self.cond.notify_one()
|
self.cond.notify_one()
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
rt::at_exit(move|:| { self.shutdown() });
|
rt::at_exit(move|:| { self.shutdown() });
|
||||||
*self.initialized.get() = true;
|
*self.initialized.get() = true;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
//! each with their own stack and local state.
|
//! each with their own stack and local state.
|
||||||
//!
|
//!
|
||||||
//! Communication between threads can be done through
|
//! Communication between threads can be done through
|
||||||
//! [channels](../../std/comm/index.html), Rust's message-passing
|
//! [channels](../../std/sync/mpsc/index.html), Rust's message-passing
|
||||||
//! types, along with [other forms of thread
|
//! types, along with [other forms of thread
|
||||||
//! synchronization](../../std/sync/index.html) and shared-memory data
|
//! synchronization](../../std/sync/index.html) and shared-memory data
|
||||||
//! structures. In particular, types that are guaranteed to be
|
//! structures. In particular, types that are guaranteed to be
|
||||||
@ -58,25 +58,45 @@
|
|||||||
//! ```rust
|
//! ```rust
|
||||||
//! use std::thread::Thread;
|
//! use std::thread::Thread;
|
||||||
//!
|
//!
|
||||||
//! let guard = Thread::spawn(move || {
|
//! let thread = Thread::spawn(move || {
|
||||||
//! println!("Hello, World!");
|
//! println!("Hello, World!");
|
||||||
//! // some computation here
|
//! // some computation here
|
||||||
//! });
|
//! });
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! The spawned thread is "detached" from the current thread, meaning that it
|
||||||
|
//! can outlive the thread that spawned it. (Note, however, that when the main
|
||||||
|
//! thread terminates all detached threads are terminated as well.) The returned
|
||||||
|
//! `Thread` handle can be used for low-level synchronization as described below.
|
||||||
|
//!
|
||||||
|
//! ## Scoped threads
|
||||||
|
//!
|
||||||
|
//! Often a parent thread uses a child thread to perform some particular task,
|
||||||
|
//! and at some point must wait for the child to complete before continuing.
|
||||||
|
//! For this scenario, use the `scoped` constructor:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use std::thread::Thread;
|
||||||
|
//!
|
||||||
|
//! let guard = Thread::scoped(move || {
|
||||||
|
//! println!("Hello, World!");
|
||||||
|
//! // some computation here
|
||||||
|
//! });
|
||||||
|
//! // do some other work in the meantime
|
||||||
//! let result = guard.join();
|
//! let result = guard.join();
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The `spawn` function doesn't return a `Thread` directly; instead, it returns
|
//! The `scoped` function doesn't return a `Thread` directly; instead, it
|
||||||
//! a *join guard* from which a `Thread` can be extracted. The join guard is an
|
//! returns a *join guard* from which a `Thread` can be extracted. The join
|
||||||
//! RAII-style guard that will automatically join the child thread (block until
|
//! guard is an RAII-style guard that will automatically join the child thread
|
||||||
//! it terminates) when it is dropped. You can join the child thread in advance
|
//! (block until it terminates) when it is dropped. You can join the child
|
||||||
//! by calling the `join` method on the guard, which will also return the result
|
//! thread in advance by calling the `join` method on the guard, which will also
|
||||||
//! produced by the thread.
|
//! return the result produced by the thread. A handle to the thread itself is
|
||||||
|
//! available via the `thread` method on the join guard.
|
||||||
//!
|
//!
|
||||||
//! If you instead wish to *detach* the child thread, allowing it to outlive its
|
//! (Note: eventually, the `scoped` constructor will allow the parent and child
|
||||||
//! parent, you can use the `detach` method on the guard,
|
//! threads to data that lives on the parent thread's stack, but some language
|
||||||
//!
|
//! changes are needed before this is possible.)
|
||||||
//! A handle to the thread itself is available via the `thread` method on the
|
|
||||||
//! join guard.
|
|
||||||
//!
|
//!
|
||||||
//! ## Configuring threads
|
//! ## Configuring threads
|
||||||
//!
|
//!
|
||||||
@ -89,7 +109,7 @@
|
|||||||
//!
|
//!
|
||||||
//! thread::Builder::new().name("child1".to_string()).spawn(move || {
|
//! thread::Builder::new().name("child1".to_string()).spawn(move || {
|
||||||
//! println!("Hello, world!")
|
//! println!("Hello, world!")
|
||||||
//! }).detach();
|
//! });
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Blocking support: park and unpark
|
//! ## Blocking support: park and unpark
|
||||||
@ -124,6 +144,8 @@
|
|||||||
//!
|
//!
|
||||||
//! * It can be implemented highly efficiently on many platforms.
|
//! * It can be implemented highly efficiently on many platforms.
|
||||||
|
|
||||||
|
#![stable]
|
||||||
|
|
||||||
use any::Any;
|
use any::Any;
|
||||||
use boxed::Box;
|
use boxed::Box;
|
||||||
use cell::UnsafeCell;
|
use cell::UnsafeCell;
|
||||||
@ -144,6 +166,7 @@ use sys_common::{stack, thread_info};
|
|||||||
|
|
||||||
/// Thread configuation. Provides detailed control over the properties
|
/// Thread configuation. Provides detailed control over the properties
|
||||||
/// and behavior of new threads.
|
/// and behavior of new threads.
|
||||||
|
#[stable]
|
||||||
pub struct Builder {
|
pub struct Builder {
|
||||||
// A name for the thread-to-be, for identification in panic messages
|
// A name for the thread-to-be, for identification in panic messages
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
@ -158,6 +181,7 @@ pub struct Builder {
|
|||||||
impl Builder {
|
impl Builder {
|
||||||
/// Generate the base configuration for spawning a thread, from which
|
/// Generate the base configuration for spawning a thread, from which
|
||||||
/// configuration methods can be chained.
|
/// configuration methods can be chained.
|
||||||
|
#[stable]
|
||||||
pub fn new() -> Builder {
|
pub fn new() -> Builder {
|
||||||
Builder {
|
Builder {
|
||||||
name: None,
|
name: None,
|
||||||
@ -169,12 +193,14 @@ impl Builder {
|
|||||||
|
|
||||||
/// Name the thread-to-be. Currently the name is used for identification
|
/// Name the thread-to-be. Currently the name is used for identification
|
||||||
/// only in panic messages.
|
/// only in panic messages.
|
||||||
|
#[stable]
|
||||||
pub fn name(mut self, name: String) -> Builder {
|
pub fn name(mut self, name: String) -> Builder {
|
||||||
self.name = Some(name);
|
self.name = Some(name);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the size of the stack for the new thread.
|
/// Set the size of the stack for the new thread.
|
||||||
|
#[stable]
|
||||||
pub fn stack_size(mut self, size: uint) -> Builder {
|
pub fn stack_size(mut self, size: uint) -> Builder {
|
||||||
self.stack_size = Some(size);
|
self.stack_size = Some(size);
|
||||||
self
|
self
|
||||||
@ -194,19 +220,41 @@ impl Builder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a new joinable thread, and return a JoinGuard guard for it.
|
/// Spawn a new detached thread, and return a handle to it.
|
||||||
///
|
///
|
||||||
/// See `Thead::spawn` and the module doc for more details.
|
/// See `Thead::spawn` and the module doc for more details.
|
||||||
pub fn spawn<T, F>(self, f: F) -> JoinGuard<T> where
|
#[unstable = "may change with specifics of new Send semantics"]
|
||||||
T: Send, F: FnOnce() -> T, F: Send
|
pub fn spawn<F>(self, f: F) -> Thread where F: FnOnce(), F: Send + 'static {
|
||||||
{
|
let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(|_| {}));
|
||||||
self.spawn_inner(Thunk::new(f))
|
unsafe { imp::detach(native) };
|
||||||
|
thread
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> JoinGuard<T> {
|
/// Spawn a new child thread that must be joined within a given
|
||||||
|
/// scope, and return a `JoinGuard`.
|
||||||
|
///
|
||||||
|
/// See `Thead::scoped` and the module doc for more details.
|
||||||
|
#[unstable = "may change with specifics of new Send semantics"]
|
||||||
|
pub fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T> where
|
||||||
|
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
|
||||||
|
{
|
||||||
let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
|
let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
|
||||||
let their_packet = Packet(my_packet.0.clone());
|
let their_packet = Packet(my_packet.0.clone());
|
||||||
|
let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(move |: ret| unsafe {
|
||||||
|
*their_packet.0.get() = Some(ret);
|
||||||
|
}));
|
||||||
|
|
||||||
|
JoinGuard {
|
||||||
|
native: native,
|
||||||
|
joined: false,
|
||||||
|
packet: my_packet,
|
||||||
|
thread: thread,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_inner<T: Send>(self, f: Thunk<(), T>, finish: Thunk<Result<T>, ()>)
|
||||||
|
-> (imp::rust_thread, Thread)
|
||||||
|
{
|
||||||
let Builder { name, stack_size, stdout, stderr } = self;
|
let Builder { name, stack_size, stdout, stderr } = self;
|
||||||
|
|
||||||
let stack_size = stack_size.unwrap_or(rt::min_stack());
|
let stack_size = stack_size.unwrap_or(rt::min_stack());
|
||||||
@ -258,21 +306,14 @@ impl Builder {
|
|||||||
unwind::try(move || *ptr = Some(f.invoke(())))
|
unwind::try(move || *ptr = Some(f.invoke(())))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
unsafe {
|
finish.invoke(match (output, try_result) {
|
||||||
*their_packet.0.get() = Some(match (output, try_result) {
|
(Some(data), Ok(_)) => Ok(data),
|
||||||
(Some(data), Ok(_)) => Ok(data),
|
(None, Err(cause)) => Err(cause),
|
||||||
(None, Err(cause)) => Err(cause),
|
_ => unreachable!()
|
||||||
_ => unreachable!()
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JoinGuard {
|
(unsafe { imp::create(stack_size, Thunk::new(main)) }, my_thread)
|
||||||
native: unsafe { imp::create(stack_size, Thunk::new(main)) },
|
|
||||||
joined: false,
|
|
||||||
packet: my_packet,
|
|
||||||
thread: my_thread,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,13 +326,12 @@ struct Inner {
|
|||||||
unsafe impl Sync for Inner {}
|
unsafe impl Sync for Inner {}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[stable]
|
||||||
/// A handle to a thread.
|
/// A handle to a thread.
|
||||||
pub struct Thread {
|
pub struct Thread {
|
||||||
inner: Arc<Inner>,
|
inner: Arc<Inner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for Thread {}
|
|
||||||
|
|
||||||
impl Thread {
|
impl Thread {
|
||||||
// Used only internally to construct a thread object without spawning
|
// Used only internally to construct a thread object without spawning
|
||||||
fn new(name: Option<String>) -> Thread {
|
fn new(name: Option<String>) -> Thread {
|
||||||
@ -304,30 +344,47 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a new joinable thread, returning a `JoinGuard` for it.
|
/// Spawn a new detached thread, returning a handle to it.
|
||||||
///
|
///
|
||||||
/// The join guard can be used to explicitly join the child thread (via
|
/// The child thread may outlive the parent (unless the parent thread is the
|
||||||
/// `join`), returning `Result<T>`, or it will implicitly join the child
|
/// main thread; the whole process is terminated when the main thread
|
||||||
/// upon being dropped. To detach the child, allowing it to outlive the
|
/// finishes.) The thread handle can be used for low-level
|
||||||
/// current thread, use `detach`. See the module documentation for additional details.
|
/// synchronization. See the module documentation for additional details.
|
||||||
pub fn spawn<T, F>(f: F) -> JoinGuard<T> where
|
#[unstable = "may change with specifics of new Send semantics"]
|
||||||
T: Send, F: FnOnce() -> T, F: Send
|
pub fn spawn<F>(f: F) -> Thread where F: FnOnce(), F: Send + 'static {
|
||||||
{
|
|
||||||
Builder::new().spawn(f)
|
Builder::new().spawn(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawn a new *scoped* thread, returning a `JoinGuard` for it.
|
||||||
|
///
|
||||||
|
/// The join guard can be used to explicitly join the child thread (via
|
||||||
|
/// `join`), returning `Result<T>`, or it will implicitly join the child
|
||||||
|
/// upon being dropped. Because the child thread may refer to data on the
|
||||||
|
/// current thread's stack (hence the "scoped" name), it cannot be detached;
|
||||||
|
/// it *must* be joined before the relevant stack frame is popped. See the
|
||||||
|
/// module documentation for additional details.
|
||||||
|
#[unstable = "may change with specifics of new Send semantics"]
|
||||||
|
pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
|
||||||
|
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
|
||||||
|
{
|
||||||
|
Builder::new().scoped(f)
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a handle to the thread that invokes it.
|
/// Gets a handle to the thread that invokes it.
|
||||||
|
#[stable]
|
||||||
pub fn current() -> Thread {
|
pub fn current() -> Thread {
|
||||||
thread_info::current_thread()
|
thread_info::current_thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cooperatively give up a timeslice to the OS scheduler.
|
/// Cooperatively give up a timeslice to the OS scheduler.
|
||||||
|
#[unstable = "name may change"]
|
||||||
pub fn yield_now() {
|
pub fn yield_now() {
|
||||||
unsafe { imp::yield_now() }
|
unsafe { imp::yield_now() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines whether the current thread is panicking.
|
/// Determines whether the current thread is panicking.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable]
|
||||||
pub fn panicking() -> bool {
|
pub fn panicking() -> bool {
|
||||||
unwind::panicking()
|
unwind::panicking()
|
||||||
}
|
}
|
||||||
@ -341,6 +398,7 @@ impl Thread {
|
|||||||
// future, this will be implemented in a more efficient way, perhaps along the lines of
|
// future, this will be implemented in a more efficient way, perhaps along the lines of
|
||||||
// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
|
// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
|
||||||
// or futuxes, and in either case may allow spurious wakeups.
|
// or futuxes, and in either case may allow spurious wakeups.
|
||||||
|
#[unstable = "recently introduced"]
|
||||||
pub fn park() {
|
pub fn park() {
|
||||||
let thread = Thread::current();
|
let thread = Thread::current();
|
||||||
let mut guard = thread.inner.lock.lock().unwrap();
|
let mut guard = thread.inner.lock.lock().unwrap();
|
||||||
@ -353,6 +411,7 @@ impl Thread {
|
|||||||
/// Atomically makes the handle's token available if it is not already.
|
/// Atomically makes the handle's token available if it is not already.
|
||||||
///
|
///
|
||||||
/// See the module doc for more detail.
|
/// See the module doc for more detail.
|
||||||
|
#[unstable = "recently introduced"]
|
||||||
pub fn unpark(&self) {
|
pub fn unpark(&self) {
|
||||||
let mut guard = self.inner.lock.lock().unwrap();
|
let mut guard = self.inner.lock.lock().unwrap();
|
||||||
if !*guard {
|
if !*guard {
|
||||||
@ -362,6 +421,7 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the thread's name.
|
/// Get the thread's name.
|
||||||
|
#[stable]
|
||||||
pub fn name(&self) -> Option<&str> {
|
pub fn name(&self) -> Option<&str> {
|
||||||
self.inner.name.as_ref().map(|s| s.as_slice())
|
self.inner.name.as_ref().map(|s| s.as_slice())
|
||||||
}
|
}
|
||||||
@ -375,6 +435,7 @@ impl thread_info::NewThread for Thread {
|
|||||||
/// Indicates the manner in which a thread exited.
|
/// Indicates the manner in which a thread exited.
|
||||||
///
|
///
|
||||||
/// A thread that completes without panicking is considered to exit successfully.
|
/// A thread that completes without panicking is considered to exit successfully.
|
||||||
|
#[stable]
|
||||||
pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
|
pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
|
||||||
|
|
||||||
struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
|
struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
|
||||||
@ -382,21 +443,24 @@ struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
|
|||||||
unsafe impl<T:'static+Send> Send for Packet<T> {}
|
unsafe impl<T:'static+Send> Send for Packet<T> {}
|
||||||
unsafe impl<T> Sync for Packet<T> {}
|
unsafe impl<T> Sync for Packet<T> {}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
/// An RAII-style guard that will block until thread termination when dropped.
|
/// An RAII-style guard that will block until thread termination when dropped.
|
||||||
///
|
///
|
||||||
/// The type `T` is the return type for the thread's main function.
|
/// The type `T` is the return type for the thread's main function.
|
||||||
pub struct JoinGuard<T> {
|
#[must_use]
|
||||||
|
#[unstable = "may change with specifics of new Send semantics"]
|
||||||
|
pub struct JoinGuard<'a, T: 'a> {
|
||||||
native: imp::rust_thread,
|
native: imp::rust_thread,
|
||||||
thread: Thread,
|
thread: Thread,
|
||||||
joined: bool,
|
joined: bool,
|
||||||
packet: Packet<T>,
|
packet: Packet<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: Send> Sync for JoinGuard<T> {}
|
#[stable]
|
||||||
|
unsafe impl<'a, T: Send + 'a> Sync for JoinGuard<'a, T> {}
|
||||||
|
|
||||||
impl<T: Send> JoinGuard<T> {
|
impl<'a, T: Send + 'a> JoinGuard<'a, T> {
|
||||||
/// Extract a handle to the thread this guard will join on.
|
/// Extract a handle to the thread this guard will join on.
|
||||||
|
#[stable]
|
||||||
pub fn thread(&self) -> &Thread {
|
pub fn thread(&self) -> &Thread {
|
||||||
&self.thread
|
&self.thread
|
||||||
}
|
}
|
||||||
@ -406,6 +470,7 @@ impl<T: Send> JoinGuard<T> {
|
|||||||
///
|
///
|
||||||
/// If the child thread panics, `Err` is returned with the parameter given
|
/// If the child thread panics, `Err` is returned with the parameter given
|
||||||
/// to `panic`.
|
/// to `panic`.
|
||||||
|
#[stable]
|
||||||
pub fn join(mut self) -> Result<T> {
|
pub fn join(mut self) -> Result<T> {
|
||||||
assert!(!self.joined);
|
assert!(!self.joined);
|
||||||
unsafe { imp::join(self.native) };
|
unsafe { imp::join(self.native) };
|
||||||
@ -414,8 +479,11 @@ impl<T: Send> JoinGuard<T> {
|
|||||||
(*self.packet.0.get()).take().unwrap()
|
(*self.packet.0.get()).take().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Send> JoinGuard<'static, T> {
|
||||||
/// Detaches the child thread, allowing it to outlive its parent.
|
/// Detaches the child thread, allowing it to outlive its parent.
|
||||||
|
#[experimental = "unsure whether this API imposes limitations elsewhere"]
|
||||||
pub fn detach(mut self) {
|
pub fn detach(mut self) {
|
||||||
unsafe { imp::detach(self.native) };
|
unsafe { imp::detach(self.native) };
|
||||||
self.joined = true; // avoid joining in the destructor
|
self.joined = true; // avoid joining in the destructor
|
||||||
@ -424,7 +492,7 @@ impl<T: Send> JoinGuard<T> {
|
|||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
#[stable]
|
#[stable]
|
||||||
impl<T: Send> Drop for JoinGuard<T> {
|
impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.joined {
|
if !self.joined {
|
||||||
unsafe { imp::join(self.native) };
|
unsafe { imp::join(self.native) };
|
||||||
@ -449,14 +517,14 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unnamed_thread() {
|
fn test_unnamed_thread() {
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
assert!(Thread::current().name().is_none());
|
assert!(Thread::current().name().is_none());
|
||||||
}).join().map_err(|_| ()).unwrap();
|
}).join().map_err(|_| ()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_named_thread() {
|
fn test_named_thread() {
|
||||||
Builder::new().name("ada lovelace".to_string()).spawn(move|| {
|
Builder::new().name("ada lovelace".to_string()).scoped(move|| {
|
||||||
assert!(Thread::current().name().unwrap() == "ada lovelace".to_string());
|
assert!(Thread::current().name().unwrap() == "ada lovelace".to_string());
|
||||||
}).join().map_err(|_| ()).unwrap();
|
}).join().map_err(|_| ()).unwrap();
|
||||||
}
|
}
|
||||||
@ -466,13 +534,13 @@ mod test {
|
|||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_join_success() {
|
fn test_join_success() {
|
||||||
match Thread::spawn(move|| -> String {
|
match Thread::scoped(move|| -> String {
|
||||||
"Success!".to_string()
|
"Success!".to_string()
|
||||||
}).join().as_ref().map(|s| s.as_slice()) {
|
}).join().as_ref().map(|s| s.as_slice()) {
|
||||||
result::Result::Ok("Success!") => (),
|
result::Result::Ok("Success!") => (),
|
||||||
@ -482,7 +550,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_join_panic() {
|
fn test_join_panic() {
|
||||||
match Thread::spawn(move|| {
|
match Thread::scoped(move|| {
|
||||||
panic!()
|
panic!()
|
||||||
}).join() {
|
}).join() {
|
||||||
result::Result::Err(_) => (),
|
result::Result::Err(_) => (),
|
||||||
@ -504,7 +572,7 @@ mod test {
|
|||||||
} else {
|
} else {
|
||||||
f(i - 1, tx);
|
f(i - 1, tx);
|
||||||
}
|
}
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
f(10, tx);
|
f(10, tx);
|
||||||
@ -518,8 +586,8 @@ mod test {
|
|||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
}
|
}
|
||||||
@ -542,7 +610,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_avoid_copying_the_body_spawn() {
|
fn test_avoid_copying_the_body_spawn() {
|
||||||
avoid_copying_the_body(|v| {
|
avoid_copying_the_body(|v| {
|
||||||
Thread::spawn(move || v.invoke(())).detach();
|
Thread::spawn(move || v.invoke(()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,14 +619,14 @@ mod test {
|
|||||||
avoid_copying_the_body(|f| {
|
avoid_copying_the_body(|f| {
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
f.invoke(());
|
f.invoke(());
|
||||||
}).detach();
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_avoid_copying_the_body_join() {
|
fn test_avoid_copying_the_body_join() {
|
||||||
avoid_copying_the_body(|f| {
|
avoid_copying_the_body(|f| {
|
||||||
let _ = Thread::spawn(move|| {
|
let _ = Thread::scoped(move|| {
|
||||||
f.invoke(())
|
f.invoke(())
|
||||||
}).join();
|
}).join();
|
||||||
})
|
})
|
||||||
@ -574,21 +642,21 @@ mod test {
|
|||||||
fn child_no(x: uint) -> Thunk {
|
fn child_no(x: uint) -> Thunk {
|
||||||
return Thunk::new(move|| {
|
return Thunk::new(move|| {
|
||||||
if x < GENERATIONS {
|
if x < GENERATIONS {
|
||||||
Thread::spawn(move|| child_no(x+1).invoke(())).detach();
|
Thread::spawn(move|| child_no(x+1).invoke(()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Thread::spawn(|| child_no(0).invoke(())).detach();
|
Thread::spawn(|| child_no(0).invoke(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple_newsched_spawn() {
|
fn test_simple_newsched_spawn() {
|
||||||
Thread::spawn(move || {}).detach();
|
Thread::spawn(move || {});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_panic_message_static_str() {
|
fn test_try_panic_message_static_str() {
|
||||||
match Thread::spawn(move|| {
|
match Thread::scoped(move|| {
|
||||||
panic!("static string");
|
panic!("static string");
|
||||||
}).join() {
|
}).join() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -602,7 +670,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_panic_message_owned_str() {
|
fn test_try_panic_message_owned_str() {
|
||||||
match Thread::spawn(move|| {
|
match Thread::scoped(move|| {
|
||||||
panic!("owned string".to_string());
|
panic!("owned string".to_string());
|
||||||
}).join() {
|
}).join() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -616,7 +684,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_panic_message_any() {
|
fn test_try_panic_message_any() {
|
||||||
match Thread::spawn(move|| {
|
match Thread::scoped(move|| {
|
||||||
panic!(box 413u16 as Box<Any + Send>);
|
panic!(box 413u16 as Box<Any + Send>);
|
||||||
}).join() {
|
}).join() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -634,7 +702,7 @@ mod test {
|
|||||||
fn test_try_panic_message_unit_struct() {
|
fn test_try_panic_message_unit_struct() {
|
||||||
struct Juju;
|
struct Juju;
|
||||||
|
|
||||||
match Thread::spawn(move|| {
|
match Thread::scoped(move|| {
|
||||||
panic!(Juju)
|
panic!(Juju)
|
||||||
}).join() {
|
}).join() {
|
||||||
Err(ref e) if e.is::<Juju>() => {}
|
Err(ref e) if e.is::<Juju>() => {}
|
||||||
@ -648,7 +716,7 @@ mod test {
|
|||||||
let mut reader = ChanReader::new(rx);
|
let mut reader = ChanReader::new(rx);
|
||||||
let stdout = ChanWriter::new(tx);
|
let stdout = ChanWriter::new(tx);
|
||||||
|
|
||||||
let r = Builder::new().stdout(box stdout as Box<Writer + Send>).spawn(move|| {
|
let r = Builder::new().stdout(box stdout as Box<Writer + Send>).scoped(move|| {
|
||||||
print!("Hello, world!");
|
print!("Hello, world!");
|
||||||
}).join();
|
}).join();
|
||||||
assert!(r.is_ok());
|
assert!(r.is_ok());
|
||||||
|
@ -86,7 +86,7 @@ pub mod __impl {
|
|||||||
/// assert_eq!(*f.borrow(), 1);
|
/// assert_eq!(*f.borrow(), 1);
|
||||||
/// *f.borrow_mut() = 3;
|
/// *f.borrow_mut() = 3;
|
||||||
/// });
|
/// });
|
||||||
/// }).detach();
|
/// });
|
||||||
///
|
///
|
||||||
/// // we retain our original value of 2 despite the child thread
|
/// // we retain our original value of 2 despite the child thread
|
||||||
/// FOO.with(|f| {
|
/// FOO.with(|f| {
|
||||||
@ -580,7 +580,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
thread_local!(static FOO: Foo = foo());
|
thread_local!(static FOO: Foo = foo());
|
||||||
|
|
||||||
Thread::spawn(|| {
|
Thread::scoped(|| {
|
||||||
assert!(FOO.state() == State::Uninitialized);
|
assert!(FOO.state() == State::Uninitialized);
|
||||||
FOO.with(|_| {
|
FOO.with(|_| {
|
||||||
assert!(FOO.state() == State::Valid);
|
assert!(FOO.state() == State::Valid);
|
||||||
@ -644,7 +644,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
drop(S1);
|
drop(S1);
|
||||||
}).join().ok().unwrap();
|
}).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
@ -662,7 +662,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::spawn(move|| unsafe {
|
Thread::scoped(move|| unsafe {
|
||||||
K1.with(|s| *s.get() = Some(S1));
|
K1.with(|s| *s.get() = Some(S1));
|
||||||
}).join().ok().unwrap();
|
}).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1137,11 +1137,11 @@ pub fn run_test(opts: &TestOpts,
|
|||||||
cfg = cfg.stderr(box stderr as Box<Writer + Send>);
|
cfg = cfg.stderr(box stderr as Box<Writer + Send>);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result_guard = cfg.spawn(move || { testfn.invoke(()) });
|
let result_guard = cfg.scoped(move || { testfn.invoke(()) });
|
||||||
let stdout = reader.read_to_end().unwrap().into_iter().collect();
|
let stdout = reader.read_to_end().unwrap().into_iter().collect();
|
||||||
let test_result = calc_result(&desc, result_guard.join());
|
let test_result = calc_result(&desc, result_guard.join());
|
||||||
monitor_ch.send((desc.clone(), test_result, stdout)).unwrap();
|
monitor_ch.send((desc.clone(), test_result, stdout)).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
match testfn {
|
match testfn {
|
||||||
|
@ -15,6 +15,6 @@ pub fn foo<T:Send + Clone>(x: T) -> Receiver<T> {
|
|||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(x.clone());
|
tx.send(x.clone());
|
||||||
}).detach();
|
});
|
||||||
rx
|
rx
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ fn run(args: &[String]) {
|
|||||||
let mut worker_results = Vec::new();
|
let mut worker_results = Vec::new();
|
||||||
for _ in range(0u, workers) {
|
for _ in range(0u, workers) {
|
||||||
let to_child = to_child.clone();
|
let to_child = to_child.clone();
|
||||||
worker_results.push(Thread::spawn(move|| {
|
worker_results.push(Thread::scoped(move|| {
|
||||||
for _ in range(0u, size / workers) {
|
for _ in range(0u, size / workers) {
|
||||||
//println!("worker {}: sending {} bytes", i, num_bytes);
|
//println!("worker {}: sending {} bytes", i, num_bytes);
|
||||||
to_child.send(request::bytes(num_bytes)).unwrap();
|
to_child.send(request::bytes(num_bytes)).unwrap();
|
||||||
@ -74,7 +74,7 @@ fn run(args: &[String]) {
|
|||||||
}
|
}
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
server(&from_parent, &to_parent);
|
server(&from_parent, &to_parent);
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
for r in worker_results.into_iter() {
|
for r in worker_results.into_iter() {
|
||||||
let _ = r.join();
|
let _ = r.join();
|
||||||
|
@ -59,7 +59,7 @@ fn run(args: &[String]) {
|
|||||||
let mut worker_results = Vec::new();
|
let mut worker_results = Vec::new();
|
||||||
let from_parent = if workers == 1 {
|
let from_parent = if workers == 1 {
|
||||||
let (to_child, from_parent) = channel();
|
let (to_child, from_parent) = channel();
|
||||||
worker_results.push(Thread::spawn(move|| {
|
worker_results.push(Thread::scoped(move|| {
|
||||||
for _ in range(0u, size / workers) {
|
for _ in range(0u, size / workers) {
|
||||||
//println!("worker {}: sending {} bytes", i, num_bytes);
|
//println!("worker {}: sending {} bytes", i, num_bytes);
|
||||||
to_child.send(request::bytes(num_bytes));
|
to_child.send(request::bytes(num_bytes));
|
||||||
@ -71,7 +71,7 @@ fn run(args: &[String]) {
|
|||||||
let (to_child, from_parent) = channel();
|
let (to_child, from_parent) = channel();
|
||||||
for _ in range(0u, workers) {
|
for _ in range(0u, workers) {
|
||||||
let to_child = to_child.clone();
|
let to_child = to_child.clone();
|
||||||
worker_results.push(Thread::spawn(move|| {
|
worker_results.push(Thread::scoped(move|| {
|
||||||
for _ in range(0u, size / workers) {
|
for _ in range(0u, size / workers) {
|
||||||
//println!("worker {}: sending {} bytes", i, num_bytes);
|
//println!("worker {}: sending {} bytes", i, num_bytes);
|
||||||
to_child.send(request::bytes(num_bytes));
|
to_child.send(request::bytes(num_bytes));
|
||||||
@ -83,7 +83,7 @@ fn run(args: &[String]) {
|
|||||||
};
|
};
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
server(&from_parent, &to_parent);
|
server(&from_parent, &to_parent);
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
for r in worker_results.into_iter() {
|
for r in worker_results.into_iter() {
|
||||||
let _ = r.join();
|
let _ = r.join();
|
||||||
|
@ -35,7 +35,7 @@ fn ping_pong_bench(n: uint, m: uint) {
|
|||||||
// Create a channel: B->A
|
// Create a channel: B->A
|
||||||
let (btx, brx) = channel();
|
let (btx, brx) = channel();
|
||||||
|
|
||||||
let guard_a = Thread::spawn(move|| {
|
let guard_a = Thread::scoped(move|| {
|
||||||
let (tx, rx) = (atx, brx);
|
let (tx, rx) = (atx, brx);
|
||||||
for _ in range(0, n) {
|
for _ in range(0, n) {
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
@ -43,7 +43,7 @@ fn ping_pong_bench(n: uint, m: uint) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let guard_b = Thread::spawn(move|| {
|
let guard_b = Thread::scoped(move|| {
|
||||||
let (tx, rx) = (btx, arx);
|
let (tx, rx) = (btx, arx);
|
||||||
for _ in range(0, n) {
|
for _ in range(0, n) {
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
|
@ -25,7 +25,7 @@ fn parfib(n: uint) -> uint {
|
|||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
tx.send(parfib(n-1));
|
tx.send(parfib(n-1));
|
||||||
}).detach();
|
});
|
||||||
let m2 = parfib(n-2);
|
let m2 = parfib(n-2);
|
||||||
return (rx.recv().unwrap() + m2);
|
return (rx.recv().unwrap() + m2);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ fn main() {
|
|||||||
let mut messages = range_step(min_depth, max_depth + 1, 2).map(|depth| {
|
let mut messages = range_step(min_depth, max_depth + 1, 2).map(|depth| {
|
||||||
use std::num::Int;
|
use std::num::Int;
|
||||||
let iterations = 2i.pow((max_depth - depth + min_depth) as uint);
|
let iterations = 2i.pow((max_depth - depth + min_depth) as uint);
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
let mut chk = 0;
|
let mut chk = 0;
|
||||||
for i in range(1, iterations + 1) {
|
for i in range(1, iterations + 1) {
|
||||||
let arena = TypedArena::new();
|
let arena = TypedArena::new();
|
||||||
|
@ -195,7 +195,7 @@ fn rendezvous(nn: uint, set: Vec<Color>) {
|
|||||||
from_rendezvous,
|
from_rendezvous,
|
||||||
to_rendezvous,
|
to_rendezvous,
|
||||||
to_rendezvous_log);
|
to_rendezvous_log);
|
||||||
}).detach();
|
});
|
||||||
to_creature
|
to_creature
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ fn fannkuch(n: i32) -> (i32, i32) {
|
|||||||
for (i, j) in range(0, N).zip(iter::count(0, k)) {
|
for (i, j) in range(0, N).zip(iter::count(0, k)) {
|
||||||
let max = cmp::min(j+k, perm.max());
|
let max = cmp::min(j+k, perm.max());
|
||||||
|
|
||||||
futures.push(Thread::spawn(move|| {
|
futures.push(Thread::scoped(move|| {
|
||||||
work(perm, j as uint, max as uint)
|
work(perm, j as uint, max as uint)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ fn main() {
|
|||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
make_sequence_processor(sz, &from_parent, &to_parent_);
|
make_sequence_processor(sz, &from_parent, &to_parent_);
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
to_child
|
to_child
|
||||||
}).collect::<Vec<Sender<Vec<u8> >> >();
|
}).collect::<Vec<Sender<Vec<u8> >> >();
|
||||||
|
@ -304,11 +304,11 @@ fn main() {
|
|||||||
|
|
||||||
let nb_freqs: Vec<_> = range(1u, 3).map(|i| {
|
let nb_freqs: Vec<_> = range(1u, 3).map(|i| {
|
||||||
let input = input.clone();
|
let input = input.clone();
|
||||||
(i, Thread::spawn(move|| generate_frequencies(input.as_slice(), i)))
|
(i, Thread::scoped(move|| generate_frequencies(input.as_slice(), i)))
|
||||||
}).collect();
|
}).collect();
|
||||||
let occ_freqs: Vec<_> = OCCURRENCES.iter().map(|&occ| {
|
let occ_freqs: Vec<_> = OCCURRENCES.iter().map(|&occ| {
|
||||||
let input = input.clone();
|
let input = input.clone();
|
||||||
Thread::spawn(move|| generate_frequencies(input.as_slice(), occ.len()))
|
Thread::scoped(move|| generate_frequencies(input.as_slice(), occ.len()))
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
for (i, freq) in nb_freqs.into_iter() {
|
for (i, freq) in nb_freqs.into_iter() {
|
||||||
|
@ -82,7 +82,7 @@ fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
|
|||||||
let mut precalc_i = Vec::with_capacity(h);
|
let mut precalc_i = Vec::with_capacity(h);
|
||||||
|
|
||||||
let precalc_futures = range(0, WORKERS).map(|i| {
|
let precalc_futures = range(0, WORKERS).map(|i| {
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
let mut rs = Vec::with_capacity(w / WORKERS);
|
let mut rs = Vec::with_capacity(w / WORKERS);
|
||||||
let mut is = Vec::with_capacity(w / WORKERS);
|
let mut is = Vec::with_capacity(w / WORKERS);
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
|
|||||||
let vec_init_r = arc_init_r.clone();
|
let vec_init_r = arc_init_r.clone();
|
||||||
let vec_init_i = arc_init_i.clone();
|
let vec_init_i = arc_init_i.clone();
|
||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
|
let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
|
||||||
let init_r_slice = vec_init_r.as_slice();
|
let init_r_slice = vec_init_r.as_slice();
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ fn par_search(masks: Vec<Vec<Vec<u64>>>) -> Data {
|
|||||||
let mut data = Data::new();
|
let mut data = Data::new();
|
||||||
search(&*masks, m, 1, List::Cons(m, &List::Nil), &mut data);
|
search(&*masks, m, 1, List::Cons(m, &List::Nil), &mut data);
|
||||||
tx.send(data).unwrap();
|
tx.send(data).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// collecting the results
|
// collecting the results
|
||||||
|
@ -35,15 +35,15 @@ fn fib(n: int) -> int {
|
|||||||
} else {
|
} else {
|
||||||
let (tx1, rx) = channel();
|
let (tx1, rx) = channel();
|
||||||
let tx2 = tx1.clone();
|
let tx2 = tx1.clone();
|
||||||
Thread::spawn(move|| pfib(&tx2, n - 1)).detach();
|
Thread::spawn(move|| pfib(&tx2, n - 1));
|
||||||
let tx2 = tx1.clone();
|
let tx2 = tx1.clone();
|
||||||
Thread::spawn(move|| pfib(&tx2, n - 2)).detach();
|
Thread::spawn(move|| pfib(&tx2, n - 2));
|
||||||
tx.send(rx.recv().unwrap() + rx.recv().unwrap());
|
tx.send(rx.recv().unwrap() + rx.recv().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
Thread::spawn(move|| pfib(&tx, n) ).detach();
|
Thread::spawn(move|| pfib(&tx, n) );
|
||||||
rx.recv().unwrap()
|
rx.recv().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ fn stress_task(id: int) {
|
|||||||
fn stress(num_tasks: int) {
|
fn stress(num_tasks: int) {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
for i in range(0, num_tasks) {
|
for i in range(0, num_tasks) {
|
||||||
results.push(Thread::spawn(move|| {
|
results.push(Thread::scoped(move|| {
|
||||||
stress_task(i);
|
stress_task(i);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -46,10 +46,10 @@ fn start(n_tasks: int, token: int) {
|
|||||||
tx.send(token);
|
tx.send(token);
|
||||||
for i in range(2, n_tasks + 1) {
|
for i in range(2, n_tasks + 1) {
|
||||||
let (tx, next_rx) = channel();
|
let (tx, next_rx) = channel();
|
||||||
Thread::spawn(move|| roundtrip(i, tx, rx)).detach();
|
Thread::spawn(move|| roundtrip(i, tx, rx));
|
||||||
rx = next_rx;
|
rx = next_rx;
|
||||||
}
|
}
|
||||||
Thread::spawn(move|| roundtrip(1, tx, rx)).detach();
|
Thread::spawn(move|| roundtrip(1, tx, rx));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn roundtrip(id: int, tx: Sender<int>, rx: Receiver<int>) {
|
fn roundtrip(id: int, tx: Sender<int>, rx: Receiver<int>) {
|
||||||
|
@ -36,7 +36,7 @@ fn main() {
|
|||||||
fn run(repeat: int, depth: int) {
|
fn run(repeat: int, depth: int) {
|
||||||
for _ in range(0, repeat) {
|
for _ in range(0, repeat) {
|
||||||
let dur = Duration::span(|| {
|
let dur = Duration::span(|| {
|
||||||
let _ = Thread::spawn(move|| {
|
let _ = Thread::scoped(move|| {
|
||||||
recurse_or_panic(depth, None)
|
recurse_or_panic(depth, None)
|
||||||
}).join();
|
}).join();
|
||||||
});
|
});
|
||||||
|
@ -35,7 +35,7 @@ fn child_generation(gens_left: uint, tx: Sender<()>) {
|
|||||||
} else {
|
} else {
|
||||||
tx.send(()).unwrap()
|
tx.send(()).unwrap()
|
||||||
}
|
}
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -15,7 +15,7 @@ use std::thread::Thread;
|
|||||||
fn f(n: uint) {
|
fn f(n: uint) {
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
while i < n {
|
while i < n {
|
||||||
let _ = Thread::spawn(move|| g()).join();
|
let _ = Thread::scoped(move|| g()).join();
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,5 +33,5 @@ fn main() {
|
|||||||
};
|
};
|
||||||
let n = args[1].parse().unwrap();
|
let n = args[1].parse().unwrap();
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
while i < n { Thread::spawn(move|| f(n) ).detach(); i += 1u; }
|
while i < n { Thread::spawn(move|| f(n) ); i += 1u; }
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let r: Result<int,_> = Thread::spawn(move|| {
|
let r: Result<int,_> = Thread::scoped(move|| {
|
||||||
panic!("test");
|
panic!("test");
|
||||||
1i
|
1i
|
||||||
}).join();
|
}).join();
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
use std::thread::Builder;
|
use std::thread::Builder;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let r: Result<int,_> = Builder::new().name("owned name".to_string()).spawn(move|| {
|
let r: Result<int,_> = Builder::new().name("owned name".to_string()).scoped(move|| {
|
||||||
panic!("test");
|
panic!("test");
|
||||||
1i
|
1i
|
||||||
}).join();
|
}).join();
|
||||||
|
@ -15,7 +15,7 @@ use std::thread::Thread;
|
|||||||
fn main() {
|
fn main() {
|
||||||
// the purpose of this test is to make sure that task::spawn()
|
// the purpose of this test is to make sure that task::spawn()
|
||||||
// works when provided with a bare function:
|
// works when provided with a bare function:
|
||||||
let r = Thread::spawn(startfn).join();
|
let r = Thread::scoped(startfn).join();
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ impl Drop for A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
let _a = A;
|
let _a = A;
|
||||||
lib::callback(|| panic!());
|
lib::callback(|| panic!());
|
||||||
1i
|
1i
|
||||||
|
@ -45,5 +45,5 @@ pub fn fails() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
Thread::spawn(fails).join();
|
Thread::scoped(fails).join();
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ pub fn test_destroy_actually_kills(force: bool) {
|
|||||||
_ = rx2.recv() => unsafe { libc::exit(1) },
|
_ = rx2.recv() => unsafe { libc::exit(1) },
|
||||||
_ = rx1.recv() => {}
|
_ = rx1.recv() => {}
|
||||||
}
|
}
|
||||||
}).detach();
|
});
|
||||||
match p.wait().unwrap() {
|
match p.wait().unwrap() {
|
||||||
ExitStatus(..) => panic!("expected a signal"),
|
ExitStatus(..) => panic!("expected a signal"),
|
||||||
ExitSignal(..) => tx.send(()).unwrap(),
|
ExitSignal(..) => tx.send(()).unwrap(),
|
||||||
|
@ -21,7 +21,7 @@ extern {
|
|||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
let i = &100i;
|
let i = &100i;
|
||||||
rust_dbg_call(callback, mem::transmute(i));
|
rust_dbg_call(callback, mem::transmute(i));
|
||||||
}).join();
|
}).join();
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
@ -37,7 +36,7 @@ mod map_reduce {
|
|||||||
for i in inputs.iter() {
|
for i in inputs.iter() {
|
||||||
let ctrl = ctrl.clone();
|
let ctrl = ctrl.clone();
|
||||||
let i = i.clone();
|
let i = i.clone();
|
||||||
Thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ).detach();
|
Thread::spawn(move|| map_task(ctrl.clone(), i.clone()) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use std::time::Duration;
|
|||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Thread::spawn(move|| customtask()).join().ok().unwrap();
|
Thread::scoped(move|| customtask()).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn customtask() {
|
fn customtask() {
|
||||||
|
@ -22,7 +22,7 @@ fn helper(rx: Receiver<Sender<()>>) {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let _t = Thread::spawn(move|| { helper(rx) }).detach();
|
let _t = Thread::spawn(move|| { helper(rx) });
|
||||||
let (snd, rcv) = channel::<int>();
|
let (snd, rcv) = channel::<int>();
|
||||||
for _ in range(1i, 100000i) {
|
for _ in range(1i, 100000i) {
|
||||||
snd.send(1i).unwrap();
|
snd.send(1i).unwrap();
|
||||||
|
@ -20,7 +20,7 @@ fn main() {
|
|||||||
// Check that both closures are capturing by value
|
// Check that both closures are capturing by value
|
||||||
assert_eq!(1, mem::size_of_val(&closure));
|
assert_eq!(1, mem::size_of_val(&closure));
|
||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
let ok = closure;
|
let ok = closure;
|
||||||
}).join().ok().unwrap();
|
}).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -24,5 +24,5 @@ pub fn main() {
|
|||||||
let mut stdin = std::io::stdin();
|
let mut stdin = std::io::stdin();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
let _ = stdin.read_to_end();
|
let _ = stdin.read_to_end();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use std::thunk::Thunk;
|
|||||||
static generations: uint = 1024+256+128+49;
|
static generations: uint = 1024+256+128+49;
|
||||||
|
|
||||||
fn spawn(f: Thunk) {
|
fn spawn(f: Thunk) {
|
||||||
Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(())).detach()
|
Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_no(x: uint) -> Thunk {
|
fn child_no(x: uint) -> Thunk {
|
||||||
|
@ -17,7 +17,7 @@ pub fn main() {
|
|||||||
|
|
||||||
tx.send("hello, world").unwrap();
|
tx.send("hello, world").unwrap();
|
||||||
|
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
println(rx.recv().unwrap());
|
println(rx.recv().unwrap());
|
||||||
}).join().ok().unwrap();
|
}).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use std::thread::Thread;
|
|||||||
pub fn main() {
|
pub fn main() {
|
||||||
let (tx, rx) = channel::<&'static str>();
|
let (tx, rx) = channel::<&'static str>();
|
||||||
|
|
||||||
let t = Thread::spawn(move|| {
|
let t = Thread::scoped(move|| {
|
||||||
assert_eq!(rx.recv().unwrap(), "hello, world");
|
assert_eq!(rx.recv().unwrap(), "hello, world");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -12,24 +12,24 @@ use std::{int, i8, i16, i32, i64};
|
|||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert!(Thread::spawn(move|| int::MIN / -1).join().is_err());
|
assert!(Thread::scoped(move|| int::MIN / -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i8::MIN / -1).join().is_err());
|
assert!(Thread::scoped(move|| i8::MIN / -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i16::MIN / -1).join().is_err());
|
assert!(Thread::scoped(move|| i16::MIN / -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i32::MIN / -1).join().is_err());
|
assert!(Thread::scoped(move|| i32::MIN / -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i64::MIN / -1).join().is_err());
|
assert!(Thread::scoped(move|| i64::MIN / -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i / 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i / 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i8 / 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i8 / 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i16 / 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i16 / 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i32 / 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i32 / 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i64 / 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i64 / 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| int::MIN % -1).join().is_err());
|
assert!(Thread::scoped(move|| int::MIN % -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i8::MIN % -1).join().is_err());
|
assert!(Thread::scoped(move|| i8::MIN % -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i16::MIN % -1).join().is_err());
|
assert!(Thread::scoped(move|| i16::MIN % -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i32::MIN % -1).join().is_err());
|
assert!(Thread::scoped(move|| i32::MIN % -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| i64::MIN % -1).join().is_err());
|
assert!(Thread::scoped(move|| i64::MIN % -1).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i % 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i % 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i8 % 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i8 % 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i16 % 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i16 % 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i32 % 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i32 % 0).join().is_err());
|
||||||
assert!(Thread::spawn(move|| 1i64 % 0).join().is_err());
|
assert!(Thread::scoped(move|| 1i64 % 0).join().is_err());
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ fn periodical(n: int) -> Receiver<bool> {
|
|||||||
Err(..) => break
|
Err(..) => break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).detach();
|
});
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ fn integers() -> Receiver<int> {
|
|||||||
}
|
}
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
}
|
}
|
||||||
}).detach();
|
});
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,4 +58,3 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ impl fmt::Show for Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
let mut f = Foo(Cell::new(0));
|
let mut f = Foo(Cell::new(0));
|
||||||
println!("{:?}", f);
|
println!("{:?}", f);
|
||||||
let Foo(ref mut f) = f;
|
let Foo(ref mut f) = f;
|
||||||
|
@ -14,7 +14,7 @@ macro_rules! expr { ($e: expr) => { $e } }
|
|||||||
|
|
||||||
macro_rules! spawn {
|
macro_rules! spawn {
|
||||||
($($code: tt)*) => {
|
($($code: tt)*) => {
|
||||||
expr!(Thread::spawn(move|| {$($code)*}).detach())
|
expr!(Thread::spawn(move|| {$($code)*}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ impl Drop for A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Thread::spawn(move|| -> () {
|
Thread::scoped(move|| -> () {
|
||||||
let _a = A;
|
let _a = A;
|
||||||
panic!();
|
panic!();
|
||||||
}).join().unwrap_err();
|
}).join().unwrap_err();
|
||||||
|
@ -33,10 +33,9 @@ impl Drop for B {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let ret = Thread::spawn(move|| {
|
let ret = Thread::scoped(move|| {
|
||||||
let _a = A { b: B { foo: 3 } };
|
let _a = A { b: B { foo: 3 } };
|
||||||
}).join();
|
}).join();
|
||||||
assert!(ret.is_err());
|
assert!(ret.is_err());
|
||||||
unsafe { assert!(dropped); }
|
unsafe { assert!(dropped); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ fn test05() {
|
|||||||
println!("{}", *three + n); // will copy x into the closure
|
println!("{}", *three + n); // will copy x into the closure
|
||||||
assert_eq!(*three, 3);
|
assert_eq!(*three, 3);
|
||||||
};
|
};
|
||||||
Thread::spawn(move|| {
|
Thread::scoped(move|| {
|
||||||
test05_start(fn_to_send);
|
test05_start(fn_to_send);
|
||||||
}).join().ok().unwrap();
|
}).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -36,5 +36,5 @@ mod b {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Thread::spawn(move|| { ::b::g() }).join().unwrap_err();
|
Thread::scoped(move|| { ::b::g() }).join().unwrap_err();
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,6 @@ fn foo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = Thread::spawn(move|| foo()).join();
|
let _ = Thread::scoped(move|| foo()).join();
|
||||||
unsafe { assert!(DTOR_COUNT == 2); }
|
unsafe { assert!(DTOR_COUNT == 2); }
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,6 @@ fn foo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = Thread::spawn(move|| foo()).join();
|
let _ = Thread::scoped(move|| foo()).join();
|
||||||
unsafe { assert!(DTOR_COUNT == 2); }
|
unsafe { assert!(DTOR_COUNT == 2); }
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,6 @@ fn iotask(_tx: &ctx, ip: String) {
|
|||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let (tx, _rx) = channel::<int>();
|
let (tx, _rx) = channel::<int>();
|
||||||
let t = Thread::spawn(move|| iotask(&tx, "localhost".to_string()) );
|
let t = Thread::scoped(move|| iotask(&tx, "localhost".to_string()) );
|
||||||
t.join().ok().unwrap();
|
t.join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
Thread::spawn(move|| child(10)).join().ok().unwrap();
|
Thread::scoped(move|| child(10)).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child(i: int) { println!("{}", i); assert!((i == 10)); }
|
fn child(i: int) { println!("{}", i); assert!((i == 10)); }
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let t = Thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) );
|
let t = Thread::scoped(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) );
|
||||||
t.join().ok().unwrap();
|
t.join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,5 +17,5 @@ use std::thread::Builder;
|
|||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut t = Builder::new();
|
let mut t = Builder::new();
|
||||||
t.spawn(move|| ()).detach();
|
t.spawn(move|| ());
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,6 @@ pub fn main() { test00(); }
|
|||||||
fn start() { println!("Started / Finished task."); }
|
fn start() { println!("Started / Finished task."); }
|
||||||
|
|
||||||
fn test00() {
|
fn test00() {
|
||||||
let _ = Thread::spawn(move|| start() ).join();
|
let _ = Thread::scoped(move|| start() ).join();
|
||||||
println!("Completing.");
|
println!("Completing.");
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ fn start(_task_number: int) { println!("Started / Finished task."); }
|
|||||||
|
|
||||||
fn test00() {
|
fn test00() {
|
||||||
let i: int = 0;
|
let i: int = 0;
|
||||||
let mut result = Thread::spawn(move|| {
|
let mut result = Thread::scoped(move|| {
|
||||||
start(i)
|
start(i)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,6 +19,6 @@ fn start(tx: &Sender<int>, start: int, number_of_messages: int) {
|
|||||||
pub fn main() {
|
pub fn main() {
|
||||||
println!("Check that we don't deadlock.");
|
println!("Check that we don't deadlock.");
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let _ = Thread::spawn(move|| { start(&tx, 0, 10) }).join();
|
let _ = Thread::scoped(move|| { start(&tx, 0, 10) }).join();
|
||||||
println!("Joined task");
|
println!("Joined task");
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ pub fn main() {
|
|||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
println!("{}", i);
|
println!("{}", i);
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
Thread::spawn({let i = i; move|| { child(i, &tx) }}).detach();
|
Thread::spawn({let i = i; move|| { child(i, &tx) }});
|
||||||
i = i - 1;
|
i = i - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,5 +18,5 @@ fn f() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let _t = Thread::spawn(move|| f() ).join();
|
let _t = Thread::scoped(move|| f() ).join();
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ fn test00() {
|
|||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
while i < number_of_tasks {
|
while i < number_of_tasks {
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
results.push(Thread::spawn({
|
results.push(Thread::scoped({
|
||||||
let i = i;
|
let i = i;
|
||||||
move|| {
|
move|| {
|
||||||
test00_start(&tx, i, number_of_messages)
|
test00_start(&tx, i, number_of_messages)
|
||||||
|
@ -24,7 +24,7 @@ fn test00() {
|
|||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let number_of_messages: int = 10;
|
let number_of_messages: int = 10;
|
||||||
|
|
||||||
let result = Thread::spawn(move|| {
|
let result = Thread::scoped(move|| {
|
||||||
test00_start(&tx, number_of_messages);
|
test00_start(&tx, number_of_messages);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ fn main() {
|
|||||||
let mut reader = ChanReader::new(rx);
|
let mut reader = ChanReader::new(rx);
|
||||||
let stderr = ChanWriter::new(tx);
|
let stderr = ChanWriter::new(tx);
|
||||||
|
|
||||||
let res = thread::Builder::new().stderr(box stderr as Box<Writer + Send>).spawn(move|| -> () {
|
let res = thread::Builder::new().stderr(box stderr as Box<Writer + Send>).scoped(move|| -> () {
|
||||||
panic!("Hello, world!")
|
panic!("Hello, world!")
|
||||||
}).join();
|
}).join();
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
|
@ -52,7 +52,7 @@ fn test() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
srv_tx.send(());
|
srv_tx.send(());
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in range(0, N) {
|
for _ in range(0, N) {
|
||||||
@ -62,7 +62,7 @@ fn test() {
|
|||||||
let _s = TcpStream::connect(addr).unwrap();
|
let _s = TcpStream::connect(addr).unwrap();
|
||||||
}
|
}
|
||||||
cli_tx.send(());
|
cli_tx.send(());
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
drop((cli_tx, srv_tx));
|
drop((cli_tx, srv_tx));
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ fn main() {
|
|||||||
timer::sleep(Duration::milliseconds(30 * 1000));
|
timer::sleep(Duration::milliseconds(30 * 1000));
|
||||||
println!("timed out!");
|
println!("timed out!");
|
||||||
unsafe { libc::exit(1) }
|
unsafe { libc::exit(1) }
|
||||||
}).detach();
|
});
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
Thread::spawn(move || -> () {
|
Thread::spawn(move || -> () {
|
||||||
@ -47,7 +47,7 @@ fn main() {
|
|||||||
stream.read_byte();
|
stream.read_byte();
|
||||||
stream.write(&[2]);
|
stream.write(&[2]);
|
||||||
}
|
}
|
||||||
}).detach();
|
});
|
||||||
let addr = rx.recv().unwrap();
|
let addr = rx.recv().unwrap();
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
@ -64,7 +64,7 @@ fn main() {
|
|||||||
Err(e) => debug!("{}", e)
|
Err(e) => debug!("{}", e)
|
||||||
}
|
}
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
}).detach();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for all clients to exit, but don't wait for the server to exit. The
|
// Wait for all clients to exit, but don't wait for the server to exit. The
|
||||||
|
@ -42,7 +42,7 @@ fn test_rm_tempdir() {
|
|||||||
tx.send(tmp.path().clone()).unwrap();
|
tx.send(tmp.path().clone()).unwrap();
|
||||||
panic!("panic to unwind past `tmp`");
|
panic!("panic to unwind past `tmp`");
|
||||||
};
|
};
|
||||||
let _ = Thread::spawn(f).join();
|
let _ = Thread::scoped(f).join();
|
||||||
let path = rx.recv().unwrap();
|
let path = rx.recv().unwrap();
|
||||||
assert!(!path.exists());
|
assert!(!path.exists());
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ fn test_rm_tempdir() {
|
|||||||
let _tmp = tmp;
|
let _tmp = tmp;
|
||||||
panic!("panic to unwind past `tmp`");
|
panic!("panic to unwind past `tmp`");
|
||||||
};
|
};
|
||||||
let _ = Thread::spawn(f).join();
|
let _ = Thread::scoped(f).join();
|
||||||
assert!(!path.exists());
|
assert!(!path.exists());
|
||||||
|
|
||||||
let path;
|
let path;
|
||||||
@ -60,7 +60,7 @@ fn test_rm_tempdir() {
|
|||||||
let f = move|:| {
|
let f = move|:| {
|
||||||
TempDir::new("test_rm_tempdir").unwrap()
|
TempDir::new("test_rm_tempdir").unwrap()
|
||||||
};
|
};
|
||||||
let tmp = Thread::spawn(f).join().ok().expect("test_rm_tmdir");
|
let tmp = Thread::scoped(f).join().ok().expect("test_rm_tmdir");
|
||||||
path = tmp.path().clone();
|
path = tmp.path().clone();
|
||||||
assert!(path.exists());
|
assert!(path.exists());
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ fn test_rm_tempdir_close() {
|
|||||||
tmp.close();
|
tmp.close();
|
||||||
panic!("panic when unwinding past `tmp`");
|
panic!("panic when unwinding past `tmp`");
|
||||||
};
|
};
|
||||||
let _ = Thread::spawn(f).join();
|
let _ = Thread::scoped(f).join();
|
||||||
let path = rx.recv().unwrap();
|
let path = rx.recv().unwrap();
|
||||||
assert!(!path.exists());
|
assert!(!path.exists());
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ fn test_rm_tempdir_close() {
|
|||||||
tmp.close();
|
tmp.close();
|
||||||
panic!("panic when unwinding past `tmp`");
|
panic!("panic when unwinding past `tmp`");
|
||||||
};
|
};
|
||||||
let _ = Thread::spawn(f).join();
|
let _ = Thread::scoped(f).join();
|
||||||
assert!(!path.exists());
|
assert!(!path.exists());
|
||||||
|
|
||||||
let path;
|
let path;
|
||||||
@ -103,7 +103,7 @@ fn test_rm_tempdir_close() {
|
|||||||
let f = move|:| {
|
let f = move|:| {
|
||||||
TempDir::new("test_rm_tempdir").unwrap()
|
TempDir::new("test_rm_tempdir").unwrap()
|
||||||
};
|
};
|
||||||
let tmp = Thread::spawn(f).join().ok().expect("test_rm_tmdir");
|
let tmp = Thread::scoped(f).join().ok().expect("test_rm_tmdir");
|
||||||
path = tmp.path().clone();
|
path = tmp.path().clone();
|
||||||
assert!(path.exists());
|
assert!(path.exists());
|
||||||
tmp.close();
|
tmp.close();
|
||||||
@ -177,7 +177,7 @@ pub fn test_rmdir_recursive_ok() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn dont_double_panic() {
|
pub fn dont_double_panic() {
|
||||||
let r: Result<(), _> = Thread::spawn(move|| {
|
let r: Result<(), _> = Thread::scoped(move|| {
|
||||||
let tmpdir = TempDir::new("test").unwrap();
|
let tmpdir = TempDir::new("test").unwrap();
|
||||||
// Remove the temporary directory so that TempDir sees
|
// Remove the temporary directory so that TempDir sees
|
||||||
// an error on drop
|
// an error on drop
|
||||||
|
@ -22,13 +22,13 @@ fn test_ret() { let _x: Box<int> = return; }
|
|||||||
|
|
||||||
fn test_panic() {
|
fn test_panic() {
|
||||||
fn f() { let _x: Box<int> = panic!(); }
|
fn f() { let _x: Box<int> = panic!(); }
|
||||||
Thread::spawn(move|| f() ).join().err().unwrap();
|
Thread::scoped(move|| f() ).join().err().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_panic_indirect() {
|
fn test_panic_indirect() {
|
||||||
fn f() -> ! { panic!(); }
|
fn f() -> ! { panic!(); }
|
||||||
fn g() { let _x: Box<int> = f(); }
|
fn g() { let _x: Box<int> = f(); }
|
||||||
Thread::spawn(move|| g() ).join().err().unwrap();
|
Thread::scoped(move|| g() ).join().err().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
@ -13,7 +13,7 @@ use std::thread::Thread;
|
|||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut i = 10;
|
let mut i = 10;
|
||||||
while i > 0 {
|
while i > 0 {
|
||||||
Thread::spawn({let i = i; move|| child(i)}).detach();
|
Thread::spawn({let i = i; move|| child(i)});
|
||||||
i = i - 1;
|
i = i - 1;
|
||||||
}
|
}
|
||||||
println!("main thread exiting");
|
println!("main thread exiting");
|
||||||
|
@ -23,7 +23,7 @@ pub fn main() {
|
|||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
Thread::spawn(move|| {
|
Thread::spawn(move|| {
|
||||||
child(&tx, i)
|
child(&tx, i)
|
||||||
}).detach();
|
});
|
||||||
expected += i;
|
expected += i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ impl Drop for Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let x = Thread::spawn(move|| {
|
let x = Thread::scoped(move|| {
|
||||||
let _b = Foo;
|
let _b = Foo;
|
||||||
}).join();
|
}).join();
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ pub fn main() {
|
|||||||
|
|
||||||
let v = main.clone();
|
let v = main.clone();
|
||||||
|
|
||||||
let _ = Thread::spawn(move|| {
|
let _ = Thread::scoped(move|| {
|
||||||
let mut v = v;
|
let mut v = v;
|
||||||
let mut panic_countdown = panic_countdown;
|
let mut panic_countdown = panic_countdown;
|
||||||
v.as_mut_slice().sort_by(|a, b| {
|
v.as_mut_slice().sort_by(|a, b| {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut result = Thread::spawn(child);
|
let mut result = Thread::scoped(child);
|
||||||
println!("1");
|
println!("1");
|
||||||
Thread::yield_now();
|
Thread::yield_now();
|
||||||
println!("2");
|
println!("2");
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use std::thread::Thread;
|
use std::thread::Thread;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut result = Thread::spawn(child);
|
let mut result = Thread::scoped(child);
|
||||||
println!("1");
|
println!("1");
|
||||||
Thread::yield_now();
|
Thread::yield_now();
|
||||||
result.join();
|
result.join();
|
||||||
|
Loading…
Reference in New Issue
Block a user