Skip to content

Commit 0efafac

Browse files
committed
auto merge of #19654 : aturon/rust/merge-rt, r=alexcrichton
This PR substantially narrows the notion of a "runtime" in Rust, and allows calling into Rust code directly without any setup or teardown. After this PR, the basic "runtime support" in Rust will consist of: * Unwinding and backtrace support * Stack guards Other support, such as helper threads for timers or the notion of a "current thread" are initialized automatically upon first use. When using Rust in an embedded context, it should now be possible to call a Rust function directly as a C function with absolutely no setup, though in that case panics will cause the process to abort. In this regard, the C/Rust interface will look much like the C/C++ interface. In more detail, this PR: * Merges `librustrt` back into `std::rt`, undoing the facade. While doing so, it removes a substantial amount of redundant functionality (such as mutexes defined in the `rt` module). Code using `librustrt` can now call into `std::rt` to e.g. start executing Rust code with unwinding support. * Allows all runtime data to be initialized lazily, including the "current thread", the "at_exit" infrastructure, and the "args" storage. * Deprecates and largely removes `std::task` along with the widespread requirement that there be a "current task" for many APIs in `std`. The entire task infrastructure is replaced with `std::thread`, which provides a more standard API for manipulating and creating native OS threads. In particular, it's possible to join on a created thread, and to get a handle to the currently-running thread. In addition, threads are equipped with some basic blocking support in the form of `park`/`unpark` operations (following a tradition in some OSes as well as the JVM). See the `std::thread` documentation for more details. * Channels are refactored to use a new internal blocking infrastructure that itself sits on top of `park`/`unpark`. One important change here is that a Rust program ends when its main thread does, following most threading models. On the other hand, threads will often be created with an RAII-style join handle that will re-institute blocking semantics naturally (and with finer control). This is very much a: [breaking-change] Closes #18000 r? @alexcrichton
2 parents 6bdce25 + 903c5a8 commit 0efafac

File tree

118 files changed

+3960
-5596
lines changed

Some content is hidden

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

118 files changed

+3960
-5596
lines changed

mk/crates.mk

+3-4
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
TARGET_CRATES := libc std flate arena term \
5353
serialize getopts collections test time rand \
54-
log regex graphviz core rbml alloc rustrt \
54+
log regex graphviz core rbml alloc \
5555
unicode
5656
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_driver rustc_trans rustc_back rustc_llvm
5757
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc regex_macros fmt_macros
@@ -62,9 +62,8 @@ DEPS_core :=
6262
DEPS_libc := core
6363
DEPS_unicode := core
6464
DEPS_alloc := core libc native:jemalloc
65-
DEPS_rustrt := alloc core libc collections native:rustrt_native
66-
DEPS_std := core libc rand alloc collections rustrt unicode \
67-
native:rust_builtin native:backtrace
65+
DEPS_std := core libc rand alloc collections unicode \
66+
native:rust_builtin native:backtrace native:rustrt_native
6867
DEPS_graphviz := std
6968
DEPS_syntax := std term serialize log fmt_macros arena libc
7069
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \

src/compiletest/runtest.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use std::io;
3232
use std::os;
3333
use std::str;
3434
use std::string::String;
35-
use std::task;
35+
use std::thread::Thread;
3636
use std::time::Duration;
3737
use test::MetricMap;
3838

@@ -445,9 +445,9 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
445445
loop {
446446
//waiting 1 second for gdbserver start
447447
timer::sleep(Duration::milliseconds(1000));
448-
let result = task::try(move || {
448+
let result = Thread::spawn(move || {
449449
tcp::TcpStream::connect("127.0.0.1:5039").unwrap();
450-
});
450+
}).join();
451451
if result.is_err() {
452452
continue;
453453
}

src/doc/guide-tasks.md

+19-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
% The Rust Tasks and Communication Guide
22

3+
**NOTE** This guide is badly out of date an needs to be rewritten.
4+
35
# Introduction
46

57
Rust provides safe concurrent abstractions through a number of core library
@@ -22,7 +24,7 @@ from shared mutable state.
2224
At its simplest, creating a task is a matter of calling the `spawn` function
2325
with a closure argument. `spawn` executes the closure in the new task.
2426

25-
```{rust}
27+
```{rust,ignore}
2628
# use std::task::spawn;
2729
2830
// Print something profound in a different task using a named function
@@ -49,7 +51,7 @@ closure is limited to capturing `Send`-able data from its environment
4951
ensures that `spawn` can safely move the entire closure and all its
5052
associated state into an entirely different task for execution.
5153

52-
```{rust}
54+
```{rust,ignore}
5355
# use std::task::spawn;
5456
# fn generate_task_number() -> int { 0 }
5557
// Generate some state locally
@@ -75,7 +77,7 @@ The simplest way to create a channel is to use the `channel` function to create
7577
of a channel, and a **receiver** is the receiving endpoint. Consider the following
7678
example of calculating two results concurrently:
7779

78-
```{rust}
80+
```{rust,ignore}
7981
# use std::task::spawn;
8082
8183
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
@@ -96,15 +98,15 @@ stream for sending and receiving integers (the left-hand side of the `let`,
9698
`(tx, rx)`, is an example of a destructuring let: the pattern separates a tuple
9799
into its component parts).
98100

99-
```{rust}
101+
```{rust,ignore}
100102
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
101103
```
102104

103105
The child task will use the sender to send data to the parent task, which will
104106
wait to receive the data on the receiver. The next statement spawns the child
105107
task.
106108

107-
```{rust}
109+
```{rust,ignore}
108110
# use std::task::spawn;
109111
# fn some_expensive_computation() -> int { 42 }
110112
# let (tx, rx) = channel();
@@ -123,7 +125,7 @@ computation, then sends the result over the captured channel.
123125
Finally, the parent continues with some other expensive computation, then waits
124126
for the child's result to arrive on the receiver:
125127

126-
```{rust}
128+
```{rust,ignore}
127129
# fn some_other_expensive_computation() {}
128130
# let (tx, rx) = channel::<int>();
129131
# tx.send(0);
@@ -154,7 +156,7 @@ spawn(move || {
154156

155157
Instead we can clone the `tx`, which allows for multiple senders.
156158

157-
```{rust}
159+
```{rust,ignore}
158160
let (tx, rx) = channel();
159161
160162
for init_val in range(0u, 3) {
@@ -179,7 +181,7 @@ Note that the above cloning example is somewhat contrived since you could also
179181
simply use three `Sender` pairs, but it serves to illustrate the point. For
180182
reference, written with multiple streams, it might look like the example below.
181183

182-
```{rust}
184+
```{rust,ignore}
183185
# use std::task::spawn;
184186
185187
// Create a vector of ports, one for each child task
@@ -203,7 +205,7 @@ getting the result later.
203205

204206
The basic example below illustrates this.
205207

206-
```{rust}
208+
```{rust,ignore}
207209
use std::sync::Future;
208210
209211
# fn main() {
@@ -230,7 +232,7 @@ called.
230232
Here is another example showing how futures allow you to background
231233
computations. The workload will be distributed on the available cores.
232234

233-
```{rust}
235+
```{rust,ignore}
234236
# use std::num::Float;
235237
# use std::sync::Future;
236238
fn partial_sum(start: uint) -> f64 {
@@ -268,7 +270,7 @@ Here is a small example showing how to use Arcs. We wish to run concurrently
268270
several computations on a single large vector of floats. Each task needs the
269271
full vector to perform its duty.
270272

271-
```{rust}
273+
```{rust,ignore}
272274
use std::num::Float;
273275
use std::rand;
274276
use std::sync::Arc;
@@ -295,7 +297,7 @@ The function `pnorm` performs a simple computation on the vector (it computes
295297
the sum of its items at the power given as argument and takes the inverse power
296298
of this value). The Arc on the vector is created by the line:
297299

298-
```{rust}
300+
```{rust,ignore}
299301
# use std::rand;
300302
# use std::sync::Arc;
301303
# fn main() {
@@ -309,7 +311,7 @@ the wrapper and not its contents. Within the task's procedure, the captured
309311
Arc reference can be used as a shared reference to the underlying vector as
310312
if it were local.
311313

312-
```{rust}
314+
```{rust,ignore}
313315
# use std::rand;
314316
# use std::sync::Arc;
315317
# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
@@ -346,17 +348,17 @@ and `()`, callers can pattern-match on a result to check whether it's an `Ok`
346348
result with an `int` field (representing a successful result) or an `Err` result
347349
(representing termination with an error).
348350

349-
```{rust}
350-
# use std::task;
351+
```{rust,ignore}
352+
# use std::thread::Thread;
351353
# fn some_condition() -> bool { false }
352354
# fn calculate_result() -> int { 0 }
353-
let result: Result<int, Box<std::any::Any + Send>> = task::try(move || {
355+
let result: Result<int, Box<std::any::Any + Send>> = Thread::spawn(move || {
354356
if some_condition() {
355357
calculate_result()
356358
} else {
357359
panic!("oops!");
358360
}
359-
});
361+
}).join();
360362
assert!(result.is_err());
361363
```
362364

src/doc/guide.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -5217,6 +5217,8 @@ the same function, so our binary is a little bit larger.
52175217
52185218
# Tasks
52195219
5220+
**NOTE**: this section is currently out of date and will be rewritten soon.
5221+
52205222
Concurrency and parallelism are topics that are of increasing interest to a
52215223
broad subsection of software developers. Modern computers are often multi-core,
52225224
to the point that even embedded devices like cell phones have more than one
@@ -5231,7 +5233,7 @@ library, and not part of the language. This means that in the future, other
52315233
concurrency libraries can be written for Rust to help in specific scenarios.
52325234
Here's an example of creating a task:
52335235
5234-
```{rust}
5236+
```{rust,ignore}
52355237
spawn(move || {
52365238
println!("Hello from a task!");
52375239
});
@@ -5261,7 +5263,7 @@ If tasks were only able to capture these values, they wouldn't be very useful.
52615263
Luckily, tasks can communicate with each other through **channel**s. Channels
52625264
work like this:
52635265
5264-
```{rust}
5266+
```{rust,ignore}
52655267
let (tx, rx) = channel();
52665268
52675269
spawn(move || {
@@ -5280,7 +5282,7 @@ which returns an `Result<T, TryRecvError>` and does not block.
52805282
52815283
If you want to send messages to the task as well, create two channels!
52825284
5283-
```{rust}
5285+
```{rust,ignore}
52845286
let (tx1, rx1) = channel();
52855287
let (tx2, rx2) = channel();
52865288
@@ -5340,7 +5342,7 @@ we'll just get the value immediately.
53405342
Tasks don't always succeed, they can also panic. A task that wishes to panic
53415343
can call the `panic!` macro, passing a message:
53425344
5343-
```{rust}
5345+
```{rust,ignore}
53445346
spawn(move || {
53455347
panic!("Nope.");
53465348
});
@@ -5349,7 +5351,7 @@ spawn(move || {
53495351
If a task panics, it is not possible for it to recover. However, it can
53505352
notify other tasks that it has panicked. We can do this with `task::try`:
53515353
5352-
```{rust}
5354+
```{rust,ignore}
53535355
use std::task;
53545356
use std::rand;
53555357

src/doc/intro.md

+17-9
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,13 @@ safe concurrent programs.
389389
Here's an example of a concurrent Rust program:
390390
391391
```{rust}
392+
use std::thread::Thread;
393+
392394
fn main() {
393395
for _ in range(0u, 10u) {
394-
spawn(move || {
396+
Thread::spawn(move || {
395397
println!("Hello, world!");
396-
});
398+
}).detach();
397399
}
398400
}
399401
```
@@ -403,7 +405,8 @@ This program creates ten threads, who all print `Hello, world!`. The
403405
double bars `||`. (The `move` keyword indicates that the closure takes
404406
ownership of any data it uses; we'll have more on the significance of
405407
this shortly.) This closure is executed in a new thread created by
406-
`spawn`.
408+
`spawn`. The `detach` method means that the child thread is allowed to
409+
outlive its parent.
407410
408411
One common form of problem in concurrent programs is a 'data race.'
409412
This occurs when two different threads attempt to access the same
@@ -418,13 +421,15 @@ problem.
418421
Let's see an example. This Rust code will not compile:
419422
420423
```{rust,ignore}
424+
use std::thread::Thread;
425+
421426
fn main() {
422427
let mut numbers = vec![1i, 2i, 3i];
423428

424429
for i in range(0u, 3u) {
425-
spawn(move || {
430+
Thread::spawn(move || {
426431
for j in range(0, 3) { numbers[j] += 1 }
427-
});
432+
}).detach();
428433
}
429434
}
430435
```
@@ -469,20 +474,21 @@ mutation doesn't cause a data race.
469474
Here's what using an Arc with a Mutex looks like:
470475
471476
```{rust}
477+
use std::thread::Thread;
472478
use std::sync::{Arc,Mutex};
473479
474480
fn main() {
475481
let numbers = Arc::new(Mutex::new(vec![1i, 2i, 3i]));
476482
477483
for i in range(0u, 3u) {
478484
let number = numbers.clone();
479-
spawn(move || {
485+
Thread::spawn(move || {
480486
let mut array = number.lock();
481487
482488
(*array)[i] += 1;
483489
484490
println!("numbers[{}] is {}", i, (*array)[i]);
485-
});
491+
}).detach();
486492
}
487493
}
488494
```
@@ -532,13 +538,15 @@ As an example, Rust's ownership system is _entirely_ at compile time. The
532538
safety check that makes this an error about moved values:
533539
534540
```{rust,ignore}
541+
use std::thread::Thread;
542+
535543
fn main() {
536544
let vec = vec![1i, 2, 3];
537545
538546
for i in range(1u, 3) {
539-
spawn(move || {
547+
Thread::spawn(move || {
540548
println!("{}", vec[i]);
541-
});
549+
}).detach();
542550
}
543551
}
544552
```

src/liballoc/arc.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use heap::deallocate;
3939
///
4040
/// ```rust
4141
/// use std::sync::Arc;
42+
/// use std::thread::Thread;
4243
///
4344
/// fn main() {
4445
/// let numbers = Vec::from_fn(100, |i| i as f32);
@@ -47,11 +48,11 @@ use heap::deallocate;
4748
/// for _ in range(0u, 10) {
4849
/// let child_numbers = shared_numbers.clone();
4950
///
50-
/// spawn(move || {
51+
/// Thread::spawn(move || {
5152
/// let local_numbers = child_numbers.as_slice();
5253
///
5354
/// // Work with the local numbers
54-
/// });
55+
/// }).detach();
5556
/// }
5657
/// }
5758
/// ```

src/libcollections/slice.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1344,8 +1344,7 @@ pub mod raw {
13441344

13451345
#[cfg(test)]
13461346
mod tests {
1347-
extern crate rustrt;
1348-
1347+
use std::boxed::Box;
13491348
use std::cell::Cell;
13501349
use std::default::Default;
13511350
use std::mem;
@@ -1629,9 +1628,10 @@ mod tests {
16291628
#[test]
16301629
fn test_swap_remove_noncopyable() {
16311630
// Tests that we don't accidentally run destructors twice.
1632-
let mut v = vec![rustrt::exclusive::Exclusive::new(()),
1633-
rustrt::exclusive::Exclusive::new(()),
1634-
rustrt::exclusive::Exclusive::new(())];
1631+
let mut v = Vec::new();
1632+
v.push(box 0u8);
1633+
v.push(box 0u8);
1634+
v.push(box 0u8);
16351635
let mut _e = v.swap_remove(0);
16361636
assert_eq!(v.len(), 2);
16371637
_e = v.swap_remove(1);
@@ -1736,7 +1736,7 @@ mod tests {
17361736
v2.dedup();
17371737
/*
17381738
* If the boxed pointers were leaked or otherwise misused, valgrind
1739-
* and/or rustrt should raise errors.
1739+
* and/or rt should raise errors.
17401740
*/
17411741
}
17421742

@@ -1750,7 +1750,7 @@ mod tests {
17501750
v2.dedup();
17511751
/*
17521752
* If the pointers were leaked or otherwise misused, valgrind and/or
1753-
* rustrt should raise errors.
1753+
* rt should raise errors.
17541754
*/
17551755
}
17561756

0 commit comments

Comments
 (0)