Skip to content

Commit a9fd41e

Browse files
committed
Fallout: move from scoped to spawn
1 parent 6e0fb70 commit a9fd41e

Some content is hidden

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

52 files changed

+128
-124
lines changed

src/doc/intro.md

+4
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ safe concurrent programs.
389389
Here's an example of a concurrent Rust program:
390390
391391
```{rust}
392+
# #![feature(scoped)]
392393
use std::thread;
393394
394395
fn main() {
@@ -421,6 +422,7 @@ problem.
421422
Let's see an example. This Rust code will not compile:
422423
423424
```{rust,ignore}
425+
# #![feature(scoped)]
424426
use std::thread;
425427
426428
fn main() {
@@ -467,6 +469,7 @@ that our mutation doesn't cause a data race.
467469
Here's what using a Mutex looks like:
468470
469471
```{rust}
472+
# #![feature(scoped)]
470473
use std::thread;
471474
use std::sync::Mutex;
472475
@@ -527,6 +530,7 @@ As an example, Rust's ownership system is _entirely_ at compile time. The
527530
safety check that makes this an error about moved values:
528531
529532
```{rust,ignore}
533+
# #![feature(scoped)]
530534
use std::thread;
531535
532536
fn main() {

src/doc/trpl/concurrency.md

+8-41
Original file line numberDiff line numberDiff line change
@@ -56,68 +56,35 @@ place!
5656

5757
## Threads
5858

59-
Rust's standard library provides a library for 'threads', which allow you to
59+
Rust's standard library provides a library for threads, which allow you to
6060
run Rust code in parallel. Here's a basic example of using `std::thread`:
6161

6262
```
6363
use std::thread;
6464
6565
fn main() {
66-
thread::scoped(|| {
66+
thread::spawn(|| {
6767
println!("Hello from a thread!");
6868
});
6969
}
7070
```
7171

72-
The `thread::scoped()` method accepts a closure, which is executed in a new
73-
thread. It's called `scoped` because this thread returns a join guard:
72+
The `thread::spawn()` method accepts a closure, which is executed in a
73+
new thread. It returns a handle to the thread, that can be used to
74+
wait for the child thread to finish and extract its result:
7475

7576
```
7677
use std::thread;
7778
7879
fn main() {
79-
let guard = thread::scoped(|| {
80-
println!("Hello from a thread!");
80+
let handle = thread::spawn(|| {
81+
"Hello from a thread!"
8182
});
8283
83-
// guard goes out of scope here
84+
println!("{}", handle.join().unwrap());
8485
}
8586
```
8687

87-
When `guard` goes out of scope, it will block execution until the thread is
88-
finished. If we didn't want this behaviour, we could use `thread::spawn()`:
89-
90-
```
91-
use std::thread;
92-
93-
fn main() {
94-
thread::spawn(|| {
95-
println!("Hello from a thread!");
96-
});
97-
98-
thread::sleep_ms(50);
99-
}
100-
```
101-
102-
We need to `sleep` here because when `main()` ends, it kills all of the
103-
running threads.
104-
105-
[`scoped`](std/thread/struct.Builder.html#method.scoped) has an interesting
106-
type signature:
107-
108-
```text
109-
fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T>
110-
where T: Send + 'a,
111-
F: FnOnce() -> T,
112-
F: Send + 'a
113-
```
114-
115-
Specifically, `F`, the closure that we pass to execute in the new thread. It
116-
has two restrictions: It must be a `FnOnce` from `()` to `T`. Using `FnOnce`
117-
allows the closure to take ownership of any data it mentions from the parent
118-
thread. The other restriction is that `F` must be `Send`. We aren't allowed to
119-
transfer this ownership unless the type thinks that's okay.
120-
12188
Many languages have the ability to execute threads, but it's wildly unsafe.
12289
There are entire books about how to prevent errors that occur from shared
12390
mutable state. Rust helps out with its type system here as well, by preventing

src/librustdoc/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,10 @@ struct Output {
130130

131131
pub fn main() {
132132
const STACK_SIZE: usize = 32000000; // 32MB
133-
let res = std::thread::Builder::new().stack_size(STACK_SIZE).scoped(move || {
133+
let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
134134
let s = env::args().collect::<Vec<_>>();
135135
main_args(&s)
136-
}).unwrap().join();
136+
}).unwrap().join().unwrap();
137137
env::set_exit_status(res as i32);
138138
}
139139

src/libstd/thread/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
//! a join before any relevant stack frames are popped:
9494
//!
9595
//! ```rust
96+
//! # #![feature(scoped)]
9697
//! use std::thread;
9798
//!
9899
//! let guard = thread::scoped(move || {

src/test/bench/shootout-binarytrees.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ fn main() {
111111
let messages = (min_depth..max_depth + 1).step_by(2).map(|depth| {
112112
use std::num::Int;
113113
let iterations = 2.pow((max_depth - depth + min_depth) as u32);
114-
thread::scoped(move || inner(depth, iterations))
114+
thread::spawn(move || inner(depth, iterations))
115115
}).collect::<Vec<_>>();
116116

117117
for message in messages {
118-
println!("{}", message.join());
118+
println!("{}", message.join().unwrap());
119119
}
120120

121121
println!("long lived tree of depth {}\t check: {}",

src/test/bench/shootout-fannkuch-redux.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,15 @@ fn fannkuch(n: i32) -> (i32, i32) {
166166
for (_, j) in (0..N).zip((0..).step_by(k)) {
167167
let max = cmp::min(j+k, perm.max());
168168

169-
futures.push(thread::scoped(move|| {
169+
futures.push(thread::spawn(move|| {
170170
work(perm, j as usize, max as usize)
171171
}))
172172
}
173173

174174
let mut checksum = 0;
175175
let mut maxflips = 0;
176176
for fut in futures {
177-
let (cs, mf) = fut.join();
177+
let (cs, mf) = fut.join().unwrap();
178178
checksum += cs;
179179
maxflips = cmp::max(maxflips, mf);
180180
}

src/test/bench/shootout-k-nucleotide.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -307,17 +307,17 @@ fn main() {
307307

308308
let nb_freqs: Vec<_> = (1..3).map(|i| {
309309
let input = input.clone();
310-
(i, thread::scoped(move|| generate_frequencies(&input, i)))
310+
(i, thread::spawn(move|| generate_frequencies(&input, i)))
311311
}).collect();
312312
let occ_freqs: Vec<_> = OCCURRENCES.iter().map(|&occ| {
313313
let input = input.clone();
314-
thread::scoped(move|| generate_frequencies(&input, occ.len()))
314+
thread::spawn(move|| generate_frequencies(&input, occ.len()))
315315
}).collect();
316316

317317
for (i, freq) in nb_freqs {
318-
print_frequencies(&freq.join(), i);
318+
print_frequencies(&freq.join().unwrap(), i);
319319
}
320320
for (&occ, freq) in OCCURRENCES.iter().zip(occ_freqs.into_iter()) {
321-
print_occurrences(&mut freq.join(), occ);
321+
print_occurrences(&mut freq.join().unwrap(), occ);
322322
}
323323
}

src/test/bench/shootout-mandelbrot.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn mandelbrot<W: old_io::Writer>(w: usize, mut out: W) -> old_io::IoResult<()> {
8282
let mut precalc_i = Vec::with_capacity(h);
8383

8484
let precalc_futures = (0..WORKERS).map(|i| {
85-
thread::scoped(move|| {
85+
thread::spawn(move|| {
8686
let mut rs = Vec::with_capacity(w / WORKERS);
8787
let mut is = Vec::with_capacity(w / WORKERS);
8888

@@ -108,7 +108,7 @@ fn mandelbrot<W: old_io::Writer>(w: usize, mut out: W) -> old_io::IoResult<()> {
108108
}).collect::<Vec<_>>();
109109

110110
for res in precalc_futures {
111-
let (rs, is) = res.join();
111+
let (rs, is) = res.join().unwrap();
112112
precalc_r.extend(rs.into_iter());
113113
precalc_i.extend(is.into_iter());
114114
}
@@ -123,7 +123,7 @@ fn mandelbrot<W: old_io::Writer>(w: usize, mut out: W) -> old_io::IoResult<()> {
123123
let vec_init_r = arc_init_r.clone();
124124
let vec_init_i = arc_init_i.clone();
125125

126-
thread::scoped(move|| {
126+
thread::spawn(move|| {
127127
let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
128128
let init_r_slice = vec_init_r;
129129

@@ -144,7 +144,7 @@ fn mandelbrot<W: old_io::Writer>(w: usize, mut out: W) -> old_io::IoResult<()> {
144144

145145
try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
146146
for res in data {
147-
try!(out.write(&res.join()));
147+
try!(out.write(&res.join().unwrap()));
148148
}
149149
out.flush()
150150
}

src/test/bench/shootout-reverse-complement.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
// ignore-android see #10393 #13206
4242

43-
#![feature(unboxed_closures, libc, old_io, collections, io, core)]
43+
#![feature(unboxed_closures, libc, old_io, collections, io, core, scoped)]
4444

4545
extern crate libc;
4646

src/test/bench/shootout-spectralnorm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
// no-pretty-expanded FIXME #15189
4242

4343
#![allow(non_snake_case)]
44-
#![feature(unboxed_closures, core, os)]
44+
#![feature(unboxed_closures, core, os, scoped)]
4545

4646
use std::iter::repeat;
4747
use std::thread;

src/test/run-fail/panic-task-name-owned.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
use std::thread::Builder;
1414

1515
fn main() {
16-
let r: () = Builder::new().name("owned name".to_string()).scoped(move|| {
16+
let r: () = Builder::new().name("owned name".to_string()).spawn(move|| {
1717
panic!("test");
1818
()
19-
}).unwrap().join();
19+
}).unwrap().join().unwrap();
2020
panic!();
2121
}

src/test/run-fail/rt-set-exit-status-panic2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn r(x:isize) -> r {
3737

3838
fn main() {
3939
error!("whatever");
40-
let _t = thread::scoped(move|| {
40+
let _t = thread::spawn(move|| {
4141
let _i = r(5);
4242
});
4343
panic!();

src/test/run-pass/atomic-print.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn main(){
2727
if env::args().count() == 2 {
2828
let barrier = sync::Arc::new(sync::Barrier::new(2));
2929
let tbarrier = barrier.clone();
30-
let t = thread::scoped(||{
30+
let t = thread::spawn(move || {
3131
tbarrier.wait();
3232
do_print(1);
3333
});

src/test/run-pass/capturing-logging.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,13 @@ impl Logger for MyWriter {
3636
fn main() {
3737
let (tx, rx) = channel();
3838
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
39-
let _t = thread::scoped(move|| {
39+
let t = thread::spawn(move|| {
4040
set_logger(box MyWriter(w) as Box<Logger+Send>);
4141
debug!("debug");
4242
info!("info");
4343
});
4444
let s = r.read_to_string().unwrap();
4545
assert!(s.contains("info"));
4646
assert!(!s.contains("debug"));
47+
t.join();
4748
}

src/test/run-pass/clone-with-exterior.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ struct Pair {
2323
pub fn main() {
2424
let z: Box<_> = box Pair { a : 10, b : 12};
2525

26-
let _t = thread::scoped(move|| {
26+
thread::spawn(move|| {
2727
assert_eq!(z.a, 10);
2828
assert_eq!(z.b, 12);
29-
});
29+
}).join();
3030
}

src/test/run-pass/comm.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ use std::sync::mpsc::{channel, Sender};
1515

1616
pub fn main() {
1717
let (tx, rx) = channel();
18-
let _t = thread::scoped(move|| { child(&tx) });
18+
let t = thread::spawn(move|| { child(&tx) });
1919
let y = rx.recv().unwrap();
2020
println!("received");
2121
println!("{}", y);
2222
assert_eq!(y, 10);
23+
t.join();
2324
}
2425

2526
fn child(c: &Sender<isize>) {

src/test/run-pass/extern-call-deep2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t {
4242
pub fn main() {
4343
// Make sure we're on a task with small Rust stacks (main currently
4444
// has a large stack)
45-
thread::scoped(move|| {
45+
thread::spawn(move|| {
4646
let result = count(1000);
4747
println!("result = {}", result);
4848
assert_eq!(result, 1000);

src/test/run-pass/extern-call-scrub.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t {
4646
pub fn main() {
4747
// Make sure we're on a task with small Rust stacks (main currently
4848
// has a large stack)
49-
let _t = thread::scoped(move|| {
49+
thread::spawn(move|| {
5050
let result = count(12);
5151
println!("result = {}", result);
5252
assert_eq!(result, 2048);
53-
});
53+
}).join();
5454
}

src/test/run-pass/fds-are-cloexec.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,19 @@ fn main() {
3434

3535
fn parent() {
3636
let file = File::open("Makefile").unwrap();
37-
let _dir = fs::read_dir("/").unwrap();
3837
let tcp1 = TcpListener::bind("127.0.0.1:0").unwrap();
39-
assert_eq!(tcp1.as_raw_fd(), file.as_raw_fd() + 2);
4038
let tcp2 = tcp1.try_clone().unwrap();
4139
let addr = tcp1.local_addr().unwrap();
42-
let t = thread::scoped(|| TcpStream::connect(addr).unwrap());
40+
let t = thread::spawn(move || TcpStream::connect(addr).unwrap());
4341
let tcp3 = tcp1.accept().unwrap().0;
44-
let tcp4 = t.join();
42+
let tcp4 = t.join().unwrap();
4543
let tcp5 = tcp3.try_clone().unwrap();
4644
let tcp6 = tcp4.try_clone().unwrap();
4745
let udp1 = UdpSocket::bind("127.0.0.1:0").unwrap();
4846
let udp2 = udp1.try_clone().unwrap();
4947

5048
let status = Command::new(env::args().next().unwrap())
5149
.arg(file.as_raw_fd().to_string())
52-
.arg((file.as_raw_fd() + 1).to_string())
5350
.arg(tcp1.as_raw_fd().to_string())
5451
.arg(tcp2.as_raw_fd().to_string())
5552
.arg(tcp3.as_raw_fd().to_string())

src/test/run-pass/init-large-type.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const SIZE: usize = 1024 * 1024;
2626

2727
fn main() {
2828
// do the test in a new thread to avoid (spurious?) stack overflows
29-
let _ = thread::scoped(|| {
29+
thread::spawn(|| {
3030
let _memory: [u8; SIZE] = unsafe { init() };
3131
}).join();
3232
}

src/test/run-pass/issue-13494.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn helper(rx: Receiver<Sender<()>>) {
2626

2727
fn main() {
2828
let (tx, rx) = channel();
29-
let _t = thread::scoped(move|| { helper(rx) });
29+
let t = thread::spawn(move|| { helper(rx) });
3030
let (snd, rcv) = channel::<isize>();
3131
for _ in 1..100000 {
3232
snd.send(1).unwrap();
@@ -38,4 +38,5 @@ fn main() {
3838
}
3939
}
4040
drop(tx);
41+
t.join();
4142
}

src/test/run-pass/issue-20454.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
use std::thread;
1414

1515
fn _foo() {
16-
let _t = thread::scoped(move || { // no need for -> ()
16+
thread::spawn(move || { // no need for -> ()
1717
loop {
1818
println!("hello");
1919
}
20-
});
20+
}).join();
2121
}
2222

2323
fn main() {}

0 commit comments

Comments
 (0)