Rust concurrency tutorial 2015 12-02
- 5. Ownership!
!
n. The act, state, or right of possessing something.
5
Borrow!
!
v. To receive something with the promise of returning it.
- 8. 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`
- 9. void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java
Take reference
to Vector
9
new Thread(…);
- 11. 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. 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
- 14. Clone
14
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Copy the String
- 16. 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).
- 20. 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
- 21. 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
- 22. 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
- 23. Methods
23
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
Store {
name: name,
prices: HashMap::new(),
}
}
}
Store::new(some_name)
- 24. 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
}
- 25. 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.”);
- 26. 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
- 27. 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
- 28. Iterators
28
for s in v.iter()
.filter(|s| s.len() > 2) {
// only strings greater than length 2
println!(“{:?}”, s);
}
(IntoIterator trait)
- 29. 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
- 30. 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;
- 32. 32
for store in stores {
let sum = compute_sum(&store, shopping_list);
if sum < best_price {
best = Some(store.name);
best_price = sum;
}
}
- 33. for store in stores {
let sum = compute_sum(&store, shopping_list);
if sum < best_price {
best = Some(store.name);
best_price = sum;
}
}
33
- 34. 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. 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>
- 37. 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;
- 39. 39
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
Or if we wanted
a response?
- 41. 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. 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. 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();
- 48. 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
- 55. 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. 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