Upload
nikomatsakis
View
1.447
Download
3
Embed Size (px)
Citation preview
The Plan
3
1. Sequential search
2. Spawn threads
3. Channels
4. Shared data
0. Hello, world!
5. Mutex
Hello, world!
4
smallcultfollowing.com/20151202/ !
Example “Hello World”
fn main() { println!(“Hello, world!”); }
Ownership!!n. The act, state, or right of possessing something.
5
Borrow!!v. To receive something with the promise of returning it.
fn main() { let name = format!(“…”); helper(name); helper(name); }
fn helper(name: String) { println!(..); } !!!
Ownership
Take ownership of a String
8
Error: use of moved value: `name`
void main() { Vector name = …; helper(name); helper(name); }
void helper(Vector name) { … } !!!
“Ownership” in Java
Take reference to Vector
9
new Thread(…);
fn main() { let name = format!(“…”); helper(&name); helper(&name); }
Shared borrow
Take a reference to a String
11
Lend the string
fn helper(name: &String) { println!(..); } !!!
13
fn main() { let name = format!(“…”); helper(&name); helper(&name); }
fn helper(name: &String) { thread::spawn(…); }
http://is.gd/cEeyzx
However: see crossbeam, simple_parallel, etc on
crates.io
Clone
14
fn main() { let name = format!(“…”); helper(name.clone()); helper(name); }
fn helper(name: String) { println!(..); } !!!Copy the String
Copy (auto-Clone)
15
fn main() { let name = 22; helper(name); helper(name); }
fn helper(name: i32) { println!(..); } !!!
i32 is a Copy type
16
Default: Type cannot be copied. Values move from place to place. Example: File descriptor. !
Clone: Type is expensive to copy, so make it explicit by calling clone(). Examples: Vector, hashtable.!!
Copy: Type is implicitly copied whenever it is referenced. Examples: u32, i32, (f32, i32).
The Plan
17
1. Sequential search
2. Spawn threads
0. Hello, world!
3. Channels
4. Shared data
5. Mutex
Declaring a structure
20
use std::collections::HashMap; !struct Store { name: String, prices: HashMap<String, f32>, }
Store
name
prices
String
HashMap
String f32
String f32
Standard traits
21
#[derive(Clone, Debug)] struct Store { name: String, prices: HashMap<String, f32>, }
Clone create explicit copies by writing `foo.clone()`Copy create implicit copies (requires Clone)Debug debug printing with `println!(“{:?}”, foo)`PartialEq equality comparisons (`foo == bar`)PartialOrd inequality comparisons (`foo > bar` etc)
…Hash hashing for a hashmap
Methods
22
struct Store { .. } !impl Store { fn add_item(&mut self, name: String, price: f32) { self.prices.insert(name, price); } ! fn price(&self, item_name: &str) -> f32 { self.prices[item_name] } }
store.add_item(…); // must be let mut store.price(…); // let OR let mut
itself an &mut method
Methods
23
struct Store { .. } !impl Store { fn new(name: String) -> Store { Store { name: name, prices: HashMap::new(), } } }
Store::new(some_name)
24
fn build_stores() -> Vec<Store> { let mut stores = vec![]; ! let mut store = Store::new(format!("R-mart")); store.add_item(format!("chocolate"), 5.0); store.add_item(format!("doll"), 22.0); store.add_item(format!("bike"), 150.0); stores.push(store); ! … ! stores // or `return stores`, as you prefer }
Basic Loops
25
let mut i = 0; while i < 3 { println!(“{:?}”, i); i += 1; }
println!(“Once you enter…”); loop { println!(“…you can never leave”); !}
!!! break; // continue works too !println!(“…oh, I guess that works. nm.”);
For Loops
26
fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } }
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
String
For Loops
27
fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &v { println!(“{:?}”, s); } }
“Alpha”
“Beta”
“Gamma”
v:
s:
&String
Iterators
28
for s in v.iter() .filter(|s| s.len() > 2) { // only strings greater than length 2 println!(“{:?}”, s); }
(IntoIterator trait)
Options and Enums
29
enum Option<T> { Some(T), None }
fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky }
http://is.gd/Gfum32
Exercise: Sequential Search
30
for s in v { … } for s in &v { … }
enum Option<T> { Some(T), None }
x.unwrap() is: match x { Some(v) => v, None => panic!() }
std::f32::INFINITY
doc.rust-lang.org/std/
if x != 0 { … }
while x != 0 { … }
println!(“{:?}”, x)
let x = Some(22); let x = None;
The Plan
31
1. Sequential search
2. Spawn threads
0. Hello, world!
3. Channels
4. Shared data
5. Mutex
32
for store in stores { let sum = compute_sum(&store, shopping_list); if sum < best_price { best = Some(store.name); best_price = sum; } }
for store in stores { let sum = compute_sum(&store, shopping_list); if sum < best_price { best = Some(store.name); best_price = sum; } }
33
34
use std::thread; … !for store in stores { let handle = thread::spawn( move || compute_sum(&store, shopping_list)); … }
Closure takes ownership
of variables it uses.
Variables used by this closure.
35
use std::thread; … !for store in stores { let handle = thread::spawn( move || compute_sum(&store, shopping_list)); let sum = handle.join().unwrap(); … }
Handle to the thread we spawned.
Wait for thread to finish and
get return value.
Thread may have panicked. Propagate.
Result<f32, Error>
36
use std::thread; … !for store in stores { let handle = thread::spawn(…); let sum = handle.join().unwrap(); … }
R-Mart
Bullseye
Woolmart
22
44
Exercise: Parallel Search
37
let mut v = vec![]; v.push(…); for item in v { }
enum Option<T> { Some(T), None }
x.unwrap() is: match x { Some(v) => v, None => panic!() }
doc.rust-lang.org/std/
if x != 0 { … }
while x != 0 { … }
println!(“{:?}”, x)
let x = Some(22); let x = None;
The Plan
38
1. Sequential search
2. Spawn threads
0. Hello, world!
3. Channels
4. Shared data
5. Mutex
39
Joining a thread allows thread to send one result.
What if we wanted multiple results?
Or if we wanted a response?
MessageMessage
rx
tx
tx
m
fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); }
40
move || { let m = Message::new(); … tx.send(m).unwrap(); }
41
rx0
tx0
let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); mem::drop(tx0);
tx1
tx2
42
for value in rx { use(value); }
loop { let value = match rx.recv() { Ok(v) => v, Err(mpsc::RecvError) => break, }; use(value); }
while let Ok(value) = rx.recv() { use(value); }
43
let (tx1, rx1) = channel(); let message = …; tx0.send((m, tx1)).unwrap(); let response = rx0.recv.unwrap();
rx0
tx0 rx1
message
tx1
response
let (tx0, rx0) = channel(); spawn(move || /* see lower-right corner below */); let (message, tx1) = rx0.recv().unwrap(); tx1.send(response).unwrap();
Exercise: Channels
44
use std::mpsc::channel;
doc.rust-lang.org/std/
let (tx, rx) = channel();
tx.send(m).unwrap();
let m = rx.recv().unwrap();
let tx1 = tx.clone();
for m in rx { … }
use std::mem::drop;
The Plan
45
1. Sequential search
2. Spawn threads
0. Hello, world!
3. Channels
4. Shared data
5. Mutex
47
use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
arc1
arc2
data
Arc => Immutable
48
use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let data = &mut arc1[0];
<anon>:6:21: 6:24 error: cannot borrow immutable borrowed content as mutable <anon>:6 let data = &mut arc[0]; ^~~
http://is.gd/nP3Pvb
49
It’s a dangling pointer!
No, it’s a data race!
No, it’s a double free!
Simultaneous Sharing and
Mutation
No, it’s iterator
invalidation!
Exercise: Shared Memory
50
use std::sync::Arc;
doc.rust-lang.org/std/
let arc1 = Arc::new(…);
let arc2 = arc1.clone();
The Plan
51
1. Sequential search
2. Spawn threads
0. Hello, world!
3. Channels
4. Shared data
5. Mutex
0
55
let counter = Mutex::new(0); { let mut data = counter.lock().unwrap(); *data += 1; }
counter
data
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
56
let counter = Mutex::new(0); let arc1 = Arc::new(counter); let arc2 = arc1.clone(); let mut data = arc1.lock(); *data += 1;
0
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
arc1
arc2
data
Exercise: Mutex
57
doc.rust-lang.org/std/
let counter = Mutex::new(0); let arc1 = Arc::new(counter); let arc2 = arc1.clone(); let mut data = arc1.lock(); *data += 1;