Auto merge of #29666 - Manishearth:rollup, r=Manishearth
- Successful merges: #29617, #29622, #29656, #29659, #29660 - Failed merges:
This commit is contained in:
commit
bb9b5f5ede
@ -1 +1 @@
|
||||
Subproject commit 93d0384373750b52996fd7f8249adaae39f562d8
|
||||
Subproject commit b6087e82ba1384c4af3adf2dc68e92316f0d4caf
|
@ -121,6 +121,7 @@ languages. It will not compile:
|
||||
|
||||
```ignore
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
let mut data = vec![1, 2, 3];
|
||||
@ -131,7 +132,7 @@ fn main() {
|
||||
});
|
||||
}
|
||||
|
||||
thread::sleep_ms(50);
|
||||
thread::sleep(Duration::from_millis(50));
|
||||
}
|
||||
```
|
||||
|
||||
@ -165,6 +166,7 @@ indivisible operations which can't have data races.
|
||||
```ignore
|
||||
use std::thread;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
let mut data = Arc::new(vec![1, 2, 3]);
|
||||
@ -176,7 +178,7 @@ fn main() {
|
||||
});
|
||||
}
|
||||
|
||||
thread::sleep_ms(50);
|
||||
thread::sleep(Duration::from_millis(50));
|
||||
}
|
||||
```
|
||||
|
||||
@ -207,6 +209,7 @@ Here's the working version:
|
||||
```rust
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
let data = Arc::new(Mutex::new(vec![1, 2, 3]));
|
||||
@ -219,7 +222,7 @@ fn main() {
|
||||
});
|
||||
}
|
||||
|
||||
thread::sleep_ms(50);
|
||||
thread::sleep(Duration::from_millis(50));
|
||||
}
|
||||
```
|
||||
|
||||
@ -241,6 +244,7 @@ Let's examine the body of the thread more closely:
|
||||
```rust
|
||||
# use std::sync::{Arc, Mutex};
|
||||
# use std::thread;
|
||||
# use std::time::Duration;
|
||||
# fn main() {
|
||||
# let data = Arc::new(Mutex::new(vec![1, 2, 3]));
|
||||
# for i in 0..3 {
|
||||
@ -250,7 +254,7 @@ thread::spawn(move || {
|
||||
data[i] += 1;
|
||||
});
|
||||
# }
|
||||
# thread::sleep_ms(50);
|
||||
# thread::sleep(Duration::from_millis(50));
|
||||
# }
|
||||
```
|
||||
|
||||
|
@ -264,6 +264,7 @@ eat. Here’s the next version:
|
||||
|
||||
```rust
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
struct Philosopher {
|
||||
name: String,
|
||||
@ -279,7 +280,7 @@ impl Philosopher {
|
||||
fn eat(&self) {
|
||||
println!("{} is eating.", self.name);
|
||||
|
||||
thread::sleep_ms(1000);
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
|
||||
println!("{} is done eating.", self.name);
|
||||
}
|
||||
@ -313,13 +314,13 @@ from the standard library, and so we need to `use` it.
|
||||
fn eat(&self) {
|
||||
println!("{} is eating.", self.name);
|
||||
|
||||
thread::sleep_ms(1000);
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
|
||||
println!("{} is done eating.", self.name);
|
||||
}
|
||||
```
|
||||
|
||||
We now print out two messages, with a `sleep_ms()` in the middle. This will
|
||||
We now print out two messages, with a `sleep` in the middle. This will
|
||||
simulate the time it takes a philosopher to eat.
|
||||
|
||||
If you run this program, you should see each philosopher eat in turn:
|
||||
@ -345,6 +346,7 @@ Here’s the next iteration:
|
||||
|
||||
```rust
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
struct Philosopher {
|
||||
name: String,
|
||||
@ -360,7 +362,7 @@ impl Philosopher {
|
||||
fn eat(&self) {
|
||||
println!("{} is eating.", self.name);
|
||||
|
||||
thread::sleep_ms(1000);
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
|
||||
println!("{} is done eating.", self.name);
|
||||
}
|
||||
@ -493,6 +495,7 @@ Let’s modify the program to use the `Table`:
|
||||
|
||||
```rust
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::sync::{Mutex, Arc};
|
||||
|
||||
struct Philosopher {
|
||||
@ -512,12 +515,12 @@ impl Philosopher {
|
||||
|
||||
fn eat(&self, table: &Table) {
|
||||
let _left = table.forks[self.left].lock().unwrap();
|
||||
thread::sleep_ms(150);
|
||||
thread::sleep(Duration::from_millis(150));
|
||||
let _right = table.forks[self.right].lock().unwrap();
|
||||
|
||||
println!("{} is eating.", self.name);
|
||||
|
||||
thread::sleep_ms(1000);
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
|
||||
println!("{} is done eating.", self.name);
|
||||
}
|
||||
@ -598,12 +601,12 @@ We now need to construct those `left` and `right` values, so we add them to
|
||||
```rust,ignore
|
||||
fn eat(&self, table: &Table) {
|
||||
let _left = table.forks[self.left].lock().unwrap();
|
||||
thread::sleep_ms(150);
|
||||
thread::sleep(Duration::from_millis(150));
|
||||
let _right = table.forks[self.right].lock().unwrap();
|
||||
|
||||
println!("{} is eating.", self.name);
|
||||
|
||||
thread::sleep_ms(1000);
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
|
||||
println!("{} is done eating.", self.name);
|
||||
}
|
||||
@ -614,8 +617,8 @@ We have three new lines. We’ve added an argument, `table`. We access the
|
||||
the fork at that particular index. That gives us access to the `Mutex` at that
|
||||
index, and we call `lock()` on it. If the mutex is currently being accessed by
|
||||
someone else, we’ll block until it becomes available. We have also a call to
|
||||
`thread::sleep_ms` between the moment first fork is picked and the moment the
|
||||
second forked is picked, as the process of picking up the fork is not
|
||||
`thread::sleep` between the moment the first fork is picked and the moment the
|
||||
second forked is picked, as the process of picking up the fork is not
|
||||
immediate.
|
||||
|
||||
The call to `lock()` might fail, and if it does, we want to crash. In this
|
||||
|
@ -24,9 +24,29 @@ compiled program, and exists for the entire duration it runs. The `greeting`
|
||||
binding is a reference to this statically allocated string. String slices
|
||||
have a fixed size, and cannot be mutated.
|
||||
|
||||
A `String`, on the other hand, is a heap-allocated string. This string is
|
||||
growable, and is also guaranteed to be UTF-8. `String`s are commonly created by
|
||||
converting from a string slice using the `to_string` method.
|
||||
String literals can span multiple lines. There are two forms. The first will
|
||||
include the newline and the leading spaces:
|
||||
|
||||
```rust
|
||||
let s = "foo
|
||||
bar";
|
||||
|
||||
assert_eq!("foo\n bar", s);
|
||||
```
|
||||
|
||||
The second, with a `\`, does not trim the spaces:
|
||||
|
||||
```rust
|
||||
let s = "foo\
|
||||
bar";
|
||||
|
||||
assert_eq!("foobar", s);
|
||||
```
|
||||
|
||||
Rust has more than just `&str`s though. A `String`, is a heap-allocated string.
|
||||
This string is growable, and is also guaranteed to be UTF-8. `String`s are
|
||||
commonly created by converting from a string slice using the `to_string`
|
||||
method.
|
||||
|
||||
```rust
|
||||
let mut s = "Hello".to_string(); // mut s: String
|
||||
|
@ -74,7 +74,9 @@ visualize what’s going on with memory. Your operating system presents a view o
|
||||
memory to your program that’s pretty simple: a huge list of addresses, from 0
|
||||
to a large number, representing how much RAM your computer has. For example, if
|
||||
you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,823`. That
|
||||
number comes from 2<sup>30</sup>, the number of bytes in a gigabyte.
|
||||
number comes from 2<sup>30</sup>, the number of bytes in a gigabyte. [^gigabyte]
|
||||
|
||||
[^gigabyte]: ‘Gigabyte’ can mean two things: 10^9, or 2^30. The SI standard resolved this by stating that ‘gigabyte’ is 10^9, and ‘gibibyte’ is 2^30. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here.
|
||||
|
||||
This memory is kind of like a giant array: addresses start at zero and go
|
||||
up to the final number. So here’s a diagram of our first stack frame:
|
||||
|
@ -344,6 +344,11 @@ pub fn is_const_fn(cstore: &cstore::CStore, did: DefId) -> bool {
|
||||
decoder::is_const_fn(&*cdata, did.index)
|
||||
}
|
||||
|
||||
pub fn is_static(cstore: &cstore::CStore, did: DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(did.krate);
|
||||
decoder::is_static(&*cdata, did.index)
|
||||
}
|
||||
|
||||
pub fn is_impl(cstore: &cstore::CStore, did: DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(did.krate);
|
||||
decoder::is_impl(&*cdata, did.index)
|
||||
|
@ -1425,6 +1425,14 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_static(cdata: Cmd, id: DefIndex) -> bool {
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
match item_family(item_doc) {
|
||||
ImmStatic | MutStatic => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
match item_family(item_doc) {
|
||||
|
@ -2875,7 +2875,8 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
sess.cstore.iter_crate_data(|cnum, _| {
|
||||
let syms = csearch::get_reachable_ids(&sess.cstore, cnum);
|
||||
reachable_symbols.extend(syms.into_iter().filter(|did| {
|
||||
csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx())
|
||||
csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx()) ||
|
||||
csearch::is_static(&sess.cstore, *did)
|
||||
}).map(|did| {
|
||||
csearch::get_symbol(&sess.cstore, did)
|
||||
}));
|
||||
|
@ -9,8 +9,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
extern void foo();
|
||||
extern char FOO_STATIC;
|
||||
|
||||
int main() {
|
||||
foo();
|
||||
return 0;
|
||||
return (int)FOO_STATIC;
|
||||
}
|
||||
|
@ -10,3 +10,6 @@
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn foo() {}
|
||||
|
||||
#[no_mangle]
|
||||
pub static FOO_STATIC: u8 = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user