Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rust or: How I Learned to Stop Worrying and Lov...

Rust or: How I Learned to Stop Worrying and Love the Compiler

Slides from a 4 hour introductory workshop to Rust.

Presented at CodeMash 2015.

Alex Burkhart

January 07, 2015
Tweet

More Decks by Alex Burkhart

Other Decks in Programming

Transcript

  1. Rust or: How I Learned to Stop Worrying and Love

    the Compiler Alex Burkhart | @saterus | Neo Innovation
  2. Installfest The Rust Compiler is ~100mb Latest Nightlies, not 0.12

    release Monday Jan 5th or newer Flash Drives being distributed
  3. "The goal is to design and implement a safe, concurrent,

    practical, static systems language." — Rust Project FAQ
  4. Practical Worse is Better Better is Good Enough Explicit >

    Implicit Not Built in a Vacuum Modern High & Low Level Design
  5. Mozilla Research Core Rust Language & Compiler Servo browser engine

    • Concurrency • Parallelism • Safety • Reliablity
  6. I/O fn main() { let hello = "Hello"; println!("{:?} {:?}!",

    hello, "World"); // => Hello World! } Compile and Run $ rustc hello.rs && ./hello
  7. Good Defaults Immutablity: let x = 2014u32; x = 0

    // => ERROR Strongly Typed: let a = 3.14_f64; let b = "100"; let c = [1u32, 2, 3]; a * b // => ERROR b / a // => ERROR c + a // => ERROR c + c // => ERROR
  8. Functions fn add(x: i32, y: i32) -> i32 { x

    + y } fn main() { let a = 100; let b = add(a, 1); println!("{:?}", b); } // => 101
  9. Enums #[derive(Show)] enum Coffee { Hot, Iced, Instant, // :'(

    } fn main() { let cold_brew: Coffee = Coffee::Iced; println!("I'll have one {:?}.", cold_brew); // => I'll have one Iced. }
  10. Enums #[derive(Show)] enum Coffee { Hot, Iced, Instant, // :'(

    } fn main() { let drink_caddy: [Coffee; 4] = [ Coffee::Iced, Coffee::Hot, Coffee::Iced, Coffee::Instant, ]; println!("Order for the whole team: {:?}", drink_caddy); // => Order for the whole team: [Iced, Hot, Iced, Instant] }
  11. Pattern Matching #[derive(Show)] enum Coffee { Hot, Iced, Instant, //

    :'( } fn main() { let cup = Coffee::Instant; let snob_approved = match cup { Coffee::Iced => true, Coffee::Hot => true, Coffee::Instant => false, }; println!("Drink from cup? {:?}", snob_approved); }
  12. Enums are Containers #[derive(Show)] enum Coffee { Hot(u8), // temp

    F Iced(bool), // still has ice Instant, // :'( } fn main() { let first_cup: Coffee = Coffee::Iced(true); let second_cup: Coffee = Coffee::Hot(212); println!("Drink {:?} then {:?}.", first_cup, second_cup); }
  13. Simpler Matching #[derive(Show)] enum Coffee { Hot(u8), // temp F

    Iced(bool), // still has ice Instant, // :'( } fn main() { let cup = Coffee::Iced(true); let snob_filtered = match cup { Instant => false, _ => true }; println!("Drink from cup? {:?}", snob_filtered); }
  14. Expressive Matching #[derive(Show)] enum Coffee { Hot(u8), // temp F

    Iced(bool), // still has ice Instant, // :'( } fn main() { let cup = Coffee::Hot(212); let safe = match cup { Coffee::Iced(x) if x => true, Coffee::Hot(120...150) => true, _ => false, }; println!("Drink from cup? {:?}", safe); }
  15. Enums in Functions fn fresh() -> Coffee { Coffee::Hot(212) }

    fn drinkable(cup: Coffee) -> bool { match cup { Coffee::Iced(x) if x => true, Coffee::Hot(120...150) => true, _ => false, } } fn main() { let cup_o_joe = fresh(); println!("Drink from cup? {:?}", drinkable(cup_o_joe)); }
  16. Static Methods on Enums #[derive(Show)] enum Coffee { Hot(u8), //

    temp F Iced(bool), // still has ice Instant, // :'( } impl Coffee { fn fresh() -> Coffee { Coffee::Hot(212) } } fn main() { let cup_o_joe = Coffee::fresh(); println!("Fresh cup of {:?}", cup_o_joe); }
  17. Instance Methods impl Coffee { fn drinkable(self) -> bool {

    match self { Coffee::Iced(x) if x => true, Coffee::Hot(120...150) => true, _ => false, } } } fn main() { let cup_o_joe = Coffee::fresh(); println!("Fresh, but drinkable?", cup_o_joe.drinkable()); }
  18. Tests #[test] fn avoid_lukewarm_coffee() { let was_hot = Coffee::Hot(72); let

    was_cold = Coffee::Iced(false); assert!( !was_hot.drinkable() ); assert!( !was_cold.drinkable() ); } $ rustc --test coffee.rs && ./coffee # compile and run tests $ rustc coffee.rs && ./coffee # compile and run program
  19. Tests (cont.) $ rustc --test coffee.rs && ./coffee # compile

    and run tests coffee.rs:5:3: 5:10 warning: variant is never used: `Instant`, #[warn(dead_code)] on by default coffee.rs:5 Instant, // :'( ^~~~~~~ coffee.rs:10:3: 12:4 warning: method is never used: `fresh`, #[warn(dead_code)] on by default coffee.rs:10 fn fresh() -> Coffee { coffee.rs:11 Coffee::Hot(212) coffee.rs:12 } coffee.rs:24:1: 28:2 warning: function is never used: `main`, #[warn(dead_code)] on by default coffee.rs:24 fn main() { coffee.rs:25 let cup_o_joe = Coffee::fresh(); coffee.rs:26 coffee.rs:27 println!("Fresh cup of {:?}", cup_o_joe); coffee.rs:28 } running 1 test test avoid_lukewarm_coffee ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
  20. Let's Build a Stoplight 1. Color enum 2. Default constructor

    -> Red 3. next_color instance method 4. Tests for both functions
  21. Tuples fn main() { let sized_coffee = (12u64, Coffee::Instant); let

    rgb: (u8, u8, u8) = (100,200,0); let (_, green, _) = rgb; println!("Medium cup: {:?}", sized_coffee); println!("Full: {:?}, Green: {:?}", rgb, green); let zero_sized = (); }
  22. Structs #[derive(Show)] struct Point { x: f64, y: f64 }

    fn main() { let origin = Point { x: 0.0, y: 0.0 }; println!("{:?}", origin); // => Point { x: 0, y: 0 } }
  23. Structs #[derive(Show)] struct Point { x: f64, y: f64 }

    impl Point { fn origin() -> Point { Point { x: 0.0, y: 0.0 } } } fn main() { let origin = Point::origin(); println!("{:?}", origin); // => Point { x: 0, y: 0 } }
  24. Complex Data Structures #[derive(Show)] struct Beverage { volume: f32, //

    oz price: u32, // cents style: Coffee, free_refills: bool, } fn main() { let great_deal = Beverage { style: Coffee::Iced(true), price: 100, free_refills: true, volume: 20.0, }; println!("I would buy {:?}.", great_deal); // => I would buy Beverage { volume: 20, price: 100, // style: Iced(true), free_refills: true }. }
  25. Arbitrarily Complex #[derive(Show)] struct Monster { current_position: Point, health_points: u32,

    favorite_drink: Coffee, } fn main() { let minotaur = Monster { current_position: Point { x: 10.0, y: 100.0 }, health_points: 20, favorite_drink: Coffee::Instant, }; println!("The minotaur has bad taste: {:?}", minotaur); // => The minotaur has bad taste: Monster { current_position: // Point { x: 10, y: 100 }, health_points: 20, favorite_drink: Instant } }
  26. I call it my billion-dollar mistake. It was the invention

    of the null reference in 1965. — C.A.R. Hoare, Author of Algol W
  27. Option Types enum Option<T> { // exact definition from standard

    library Some(T), None } fn main() { let a: Option<u32> = Some(10); let b: Option<u32> = None; let c: Option<Coffee> = Some(Coffee::Instant); let d: Option<Coffee> = None; println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d); // => Some(10), None, Some(Instant), None b == d; // => error: mismatched types... *snip* }
  28. Option Types (cont.) enum Option<T> { // exact definition from

    standard library Some(T), None } fn main() { let a = Some(10u32); let b = None; let squared = match a { Some(x) => x * x, None => 0 }; let either = b.or(a); println!("Squared: {:?}, Either: {:?}", squared, either); // => Squared: 100, Either: Some(10) }
  29. Let's Build a Treasure Hunter 1. Make Point, Archaeologist, &

    Treasure structs 2. Write a default constructor for Point 3. Write a function that returns the treasures's position if it has not been disturbed 4. Write a function that gives (x,y) directions from the Archaeologist to the Treasure 5. Write tests for all 3 functions
  30. Result enum Result<T,E> { // exact definition from standard library

    Ok(T), Err(E), } fn main() { let pot_contents = Coffee::Hot(180); let could_fail = match pot_contents { cup @ Coffee::Hot(130...212) => Ok(cup), _ => Err("Time to brew a new pot."), }; let no_excuses: Option<Coffee> = could_fail.ok(); let cant_wait = no_excuses.unwrap_or("To the coffee shop!"); }
  31. Strings use std::ascii::AsciiExt; fn main() { let polite = "Hello";

    let rude = polite.to_ascii_uppercase(); println!("{:?} is polite.", polite); println!("{:?} is rude.", rude); }
  32. String Slices use std::ascii::AsciiExt; fn main() { let polite: &str

    = "Hello"; // string slice let rude: String = polite.to_ascii_uppercase(); // string println!("{:?} is polite.", polite); println!("{:?} is rude.", rude); }
  33. Stack & Heap Memory fn main() { let stack: Color

    = Color::Red; let heap: Box<Color> = box Color::Green; println!("stack: {:?}, heap: {:?}", stack, heap); // end of scope, memory gets freed }
  34. Stack & Heap Memory fn main() { let stack: Color

    = Color::Red; let heap: Box<Color> = box Color::Green; // C: int *ptr = malloc(sizeof(Color)); println!("stack: {:?}, heap: {:?}", stack, heap); // end of scope, memory gets freed // C: free(heap); }
  35. Ownership fn main() { let r = box Color::Red; //

    allocate some memory println!("the value of r: {:?}", r); // access r let color = r; // transfer ownership to `color` println!("the value of color: {:?}", color); // access color println!("the value of color: {:?}", r); // => error: use of moved value: `r` // owner `color` falls out of scope // owner drops its property }
  36. Borrowing fn main() { let r: Box<Color> = box Color::Red;

    // allocate some memory println!("the value of r: {:?}", r); // access r let color: &Box<Color> = &r; // borrow a reference // access borrowed value println!("the value of color: {:?}", color); // access owned value println!("the value of color: {:?}", r); // borrower & owner are both dropped }
  37. Borrow Checker fn main() { let x = box 2014u32;

    { // introduce new scope let y = &x; println!("x: {:?}, y: {:?}", x, y); } // y is dropped println!("{:?}", x); } // x is dropped
  38. Strings Revisited use std::ascii::AsciiExt; fn main() { let polite: &str

    = "Hello"; let rude: String = polite.to_ascii_uppercase(); println!("{:?} is polite.", polite); println!("{:?} is rude.", rude); // polite is dropped, but it owns nothing // rude is dropped, its owned str primitive is dropped }
  39. Why Ownership? fn main() { let x: Vec<Color> = vec![Color::Red,

    Color::Green, Color::Red]; // if we shallow copied... let y = x; // x frees its vector contents // y frees the *same* vector contents // double free! SEGFAULT }
  40. Ownership Saves the Day fn main() { let x: Vec<Color>

    = vec![Color::Red, Color::Green, Color::Red]; // the ownership of the vec *moves* to y let y = x; println!("{:?}", y); // => ok, y owns it println!("{:?}", x); // => error! use of moved value // x is already invalidated // y frees the vector contents }
  41. Movement & Borrowing fn main() { let x = box

    Color::Green; // x is the owner of memory let y = &x; // y borrows x // everyone can read immutably borrowed memory! println!("{:?}", x); // ok! println!("{:?}", y); // ok! let k = x; // => error: cannot move out of `x` because it is borrowed }
  42. Moving Copying Borrowed References fn main() { let x =

    box Color::Green; // x is the owner of memory let y = &x; // y borrows x // everyone can read immutably borrowed memory! println!("{:?}", x); // ok! println!("{:?}", y); // ok! // *copy* the reference to the Box let k = y; println!("{:?}", k); // ok! println!("{:?}", y); // ok! }
  43. Ownership Returning Functions fn fresh_pot() -> Coffee { Coffee::Hot(212) }

    fn main() { let cup = box fresh_pot(); drink_coffee(cup); } fn dangling_pointer() -> &Coffee { let failure = Coffee::Instant; &failure }
  44. Ownership Taking Functions fn drink_coffee(owned: Box<Coffee>) { if is_acceptable(&*owned) {

    println!("Bliss..."); } else { println!("This is unacceptable!"); } } fn is_acceptable(borrowed: &Coffee) -> bool { match *borrowed { Coffee::Iced(x) if x => true, Coffee::Hot(temp) if temp > 140 => true, _ => false, } }
  45. Methods Revisited impl Coffee { fn drinkable(&self) -> bool {

    match *self { Coffee::Iced(x) if x => true, Coffee::Hot(120...150) => true, _ => false, } } } fn main() { let cup = box fresh_pot(); let drinkable = cup.drinkable(); println!("{:?} is drinkable? {:?}", cup, drinkable); }
  46. Slices fn main() { let vector: Vec<u32> = vec![1, 2,

    3]; let v_slice: &[u32] = vector.as_slice(); println!("{:?} and {:?} are the same *exact* data!", vector, v_slice); }
  47. Let's Build a Better Stoplight 1. Implement a "peek_next" method

    for your stoplight Color 2. Heap allocate a Color, borrow it, peek at it with the borrow 3. Write a "go_through" method for your stoplight Color, return a Result 4. Don't forget to write your tests!
  48. Polymorphic Types fn main() { let file_size: Result<u64, String> =

    Ok(2_000_000); let cup: Result<Coffee, String> = Ok(Coffee::Hot(150)); let vector: Vec<u32> = vec![1, 2, 3, 4, 5]; let map: HashMap<String, f64> = HashMap::new(); let opt: Option<Vec<u32>> = Some(vector); }
  49. Polymorphism (poly = many) + (morph = shape) Parametric Polymorphism

    = Vec<T> Subtyping = Inheritance Ad-hoc Polymorphism = Overloading & Traits
  50. Traits trait Area { fn area(&self) -> f64; } impl

    Area for Circle { fn area(&self) -> f64 { self.radius * self.radius * 3.141593 } } fn main() { let c = Circle { radius: 10.0, location: Point::origin() }; let h = Hexagon { side_length: 10.0, location: Point::origin() }; println!("circle: {:?}, hexagon: {:?}", c.area(), h.area()); }
  51. Trait Bounds impl Eq for String { // details omitted

    } impl Hash for String { // details omitted } impl<K: Eq + Hash, V> MyHashMap<K,V> { // details omitted } fn main() { let map: HashMap<String, u32> = HashMap::new(); // compiles! } // note: not quite the std lib implementations...
  52. Trait Bounds (cont.) impl Vec<T> { fn contains<T: PartialEq>(&self, target:

    T) -> bool { // details omitted } fn sum<T: Add<T>>(&self) -> T { // details omitted } } impl<T: Show> Show for Vec<T> { // details omitted } // note: not real std lib things...
  53. std::ops • Show: fmt() • Eq: == • PartialEq: eq(),

    ne() • Ord: cmp() • PartialOrd: >=, <=, >, < • Add: + • Deref: unary * • Index: []
  54. Kinds • Copy: memcpy friendly • Sized: compile-time known size

    • Sync: threadsafe • Send: cross task boundary
  55. Copy vs Clone Copy - implicitly copyable - compiler driven

    - copy the bits Clone - manually cloneable - explicit .clone() call - create a new thing
  56. Assignment Operator Revisited fn main() { // u32 implements Copy

    let a = 100u32; let b = a; // b is a new copy // Coffee does _not_ impl Copy let c = Coffee::Hot(212); let d = c; // ownership of existing Coffee *moved* to d }
  57. ~Assignment Operator~ Name Binding Revisited fn main() { // (u32,u32,u32)

    implements Copy let a = (0u32, 2, 5); // when x is bound, it is *copied* let b = match a { (x,_,_) if x > 0 => x * x, (_,x,_) if x > 0 => x * x, (_,_,x) if x > 0 => x * x, _ => 0 }; println!("a: {:?}, b: {:?}", a, b); }
  58. Name Binding Revisited fn main() { let cup = Coffee::Hot(150);

    // ownership of the coffee is moved let microwaved = match cup { Coffee::Hot(x) if x < 130 => Coffee::Hot(200), hot @ Coffee::Hot(_) => hot, _ => Coffee::Hot(212), }; println!("cup: {:?}, microwaved: {:?}", cup, microwaved); // => error: use of moved value: `cup` }
  59. Closures fn main() { let ten = 10_i64; let plus_ten

    = |value| ten + value; let minus_ten = |value: i64| -> i64 { value - ten }; println!("{:?} + {:?} = {:?}", ten, 4, plus_ten(4)); println!("{:?} + {:?} = {:?}", ten, 2000, plus_ten(2000)); println!("{:?} - {:?} = {:?}", -90, ten, minus_ten(-90)); }
  60. Closures (cont.) fn main() { let nums = range(0, 100).collect::<Vec<u32>>();

    let even_cubes: Vec<u32> = nums.into_iter() .map(|n| n * n * n ) .filter(|n| *n % 2 == 0 ) .skip(5) .take(10) .collect(); println!("even_cubes: {:?}", even_cubes); }
  61. Iterator trait Iterator<A> { fn next(&mut self) -> Option<A>; }

    fn main() { for n in range(0u32, 10) { println!("n: {:?}", n); } }
  62. Iterators.next() fn main() { let seq: [Color; 3] = [

    Color::Green, Color::Yellow, Color::Red ]; let timing: Vec<u32> = vec![20, 4, 10]; let mut stoplight = seq.iter() .zip(timing.iter()) .cycle(); for (color, time) in stoplight { println!("{:?} for {:?}s", color, time); } }
  63. Mutability fn main() { let x = box Color::Red; *x

    = Color::Green; // => error: re-assignment of immutable variable `x` // move to mutable ownership let mut y = x; *y = Color::Green; // move to immutable ownership let z = y; println!("{:?}", z); }
  64. Mutability is Greedy fn main() { let mut x =

    box Color::Red; { let y = &mut x; let z = &mut x; // => error! cannot borrow `x` as // mutable more than once at a time x = box Color::Yellow; // => error! cannot assign to `x` // because it is borrowed *y = box Color::Green; // => ok! } println!("{:?}", x); // => Color::Green }
  65. Mutability w/ Functions fn update_position(point: &mut Point, x: f64, y:

    f64) -> () { point.x = x; point.y = y; } fn reset(point: &mut Point) -> () { update_position(point, 0.0, 0.0); } fn dup(original: &Point) -> Point { Point { x: original.x, y: original.y } }
  66. Mutability w/ Functions (cont.) fn main() { let foo: Point

    = Point { x: 25.0, y: 25.0 }; reset(&mut foo); // => error! can't take mutable reference of immutable variable let mut foo = foo; // transfer ownership to mutable scope { let ref_foo = &foo; // takes a immutable reference let bar = dup(ref_foo); println!("Copy: {:?}", bar); // immutable ref to foo falls out of scope } reset(&mut foo); // takes a mutable reference println!("New Position: {:?}", foo); }
  67. Iterators.next() let mut r = range(0u8, 10); loop { match

    r.next() { None => break, Some(n) => { println!("n: {:?}" , n); } } } for n in range(0u8, 10) { println!("n: {:?}" , n); }
  68. Randomness use std::rand; fn main() { let x: f32 =

    rand::random(); println!("x: {:?}", x); }
  69. Let's Build a BattleBot! 1. Make a BattleBot struct. 2.

    Make functions that heal it, or hurt it. 3. Make a Weapon type. 4. Make a function that prints all the bot's weapons. 5. Make an attack function. 6. impl Rand for BattleBot 7. Make a randomly generated BattleBot royale!
  70. Modules // in project_a/src/traffic/color.rs mod traffic { pub enum Color

    { Red, Yellow, Green }; } // in project_b/src/main.rs extern crate project_a; // link to project_a use traffic::Color; // import type from `traffic` module fn main() { let stoplight = Color::Red; println!("Imported a {:?} stoplight!", stoplight); }
  71. Namespaced Enums // in project_a/src/traffic/color.rs mod traffic { pub enum

    Color { Red, Yellow, Green }; } // in project_b/src/main.rs extern crate project_a; use traffic::Color{Red,Yellow,Green}; fn main() { let stoplight = Red; println!("Imported a {:?} stoplight!", stoplight); }
  72. Private Struct Fields // in project_a/src/graphics/point.rs mod graphics { #[derive(Show)]

    pub struct Point { pub x: f64, pub y: f64, _hidden: u8, } impl Point { pub fn origin() -> Point { Point { x: 0.0, y: 0.0, _hidden: 157 } } } } // in project_b/src/main.rs extern crate project_a; use graphics::Point; fn main() { let p1 = Point::origin(); println!("Imported a: {:?}", p1); // => Imported a: Point { x: 0, y: 0, _hidden: 157 } }
  73. Re-Exports // in project_a/src/traffic/color.rs mod traffic { pub enum Color

    { Red, Yellow, Green }; } // in project_b/src/city_planning/roadways.rs extern crate project_a; pub use traffic::Color{Red,Yellow,Green}; // in project_c/src/main.rs extern crate project_b; use city_planning::roadways::Color;
  74. Module File Structure $ tree rustc/src/librand rustc/src/librand ├── distributions #

    <-- rand::distributions │ ├── exponential.rs │ ├── gamma.rs │ ├── mod.rs │ ├── normal.rs # <-- rand::distributions::normal │ ├── range.rs │ └── ziggurat_tables.rs ├── isaac.rs ├── lib.rs # <-- rand (main module defn) ├── rand_impls.rs └── reseeding.rs # <-- rand::reseeding
  75. Cargo Package Manager Ruby Gems + Bundler + rubygems.org cargo

    new cargo build cargo test cargo run cargo doc Cargo.toml & Cargo.lock list and lock deps
  76. Cargo.toml [package] name = "testing" version = "0.0.1" authors =

    ["Alex Burkhart <[email protected]>"] [dependencies] stainless = "~0.0.3" [dependencies.time] git = https://github.com/rust-lang/time.git
  77. Let's Read Some Docs! 1. Familiarize yourself with an interesting

    type • Option • Vec • Box • Iterator • std::io 2. Get some Coffee!
  78. Threads use std::sync::mpsc::channel; use std::thread::Thread; fn main() { let (tx,

    rx) = channel(); Thread::spawn(move || { tx.send("Data produced in child task").unwrap(); }).detach(); let data = rx.recv().unwrap(); println!("{:?}", data); // 1x => Data produced in child task }
  79. Multiple Threads use std::sync::mpsc::channel; use std::thread::Thread; fn main() { let

    (tx, rx) = channel(); for task_num in range(0u8, 8) { let tx = tx.clone(); // <-- will be captured by thread Thread::spawn(move || { let msg = format!("Task {:?} done!", task_num); tx.send(msg).unwrap(); }).detach(); } for _ in range(0u8, 8) { let data = rx.recv().unwrap(); println!("{:?}", data); } // 10x => Task N done! }
  80. Big Data Syncs! use std::sync::Arc; use std::sync::mpsc::channel; use std::thread::Thread; #[derive(Show)]

    struct HugeStruct { huge_name: String // probably additional fields... } impl HugeStruct { fn new() -> HugeStruct { HugeStruct { huge_name: "I'M HUGE".to_string() } } }
  81. Shared Immutable Memory fn main() { let (tx, rx) =

    channel(); let huge_struct = Arc::new(HugeStruct::new()); for task_num in range(0u8, 8) { let tx = tx.clone(); let huge_struct = huge_struct.clone(); spawn(proc() { let msg = format!("Task {:?}: Accessed {:?}", task_num, huge_struct.huge_name); tx.send(msg); }); } drop(tx); // => force last transmitter to hang up for data in rx.iter() { println!("{:?}", data); // 10x => Task N: Accessed I'M HUGE } }
  82. Shared Mutable Memory use std::io::timer::sleep; use std::rand; use std::sync::Arc; use

    std::sync::Mutex; use std::sync::mpsc::channel; use std::thread::Thread; use std::time::duration::Duration; #[derive(Show)] struct HugeStruct { huge_name: String, access_count: u8 } impl HugeStruct { fn new() -> HugeStruct { HugeStruct { huge_name: "I'M HUGE".to_string(), access_count: 0 } } } fn random_sleep() { let n = rand::random::<i64>() % 10; let duration = Duration::milliseconds(n * n); sleep(duration); }
  83. Shared Mutable Memory fn main() { let (tx, rx) =

    channel(); let huge_struct = HugeStruct::new(); let huge_struct = Arc::new(Mutex::new(huge_struct)); for task_num in range(0u8, 8) { let tx = tx.clone(); let huge_struct = huge_struct.clone(); // clone the arc Thread::spawn(move || { random_sleep(); // <-- without this, they always grab the lock in spawn order let mut inner_struct = huge_struct.lock().unwrap(); inner_struct.access_count += 1; let msg = format!("Task {:?}: Accessed Count {:?}", task_num, inner_struct.access_count); tx.send(msg).unwrap(); }).detach(); } drop(tx); // => force last transmitter to hang up for data in rx.iter() { println!("{:?}", data); // 10x => Task N: Accessed I'M HUGE } }
  84. Let's Implement DEFLATE! 1. Wiki the DEFLATE algorithm 2. Break

    off a small part of the problem 3. Victory! 4. Decide to parallelize what you can 5. Enlightenment Achieved!
  85. Attributions struct2.jpg https://secure.flickr.com/photos/ zigazou76/7670875192/ green_stoplight.jpg https://secure.flickr.com/photos/ jstanphoto/4744085931/ ie6acid2.png "Ieacid2" by

    Acid2 Task Force - https:// commons.wikimedia.org/wiki/File:Ieacid2.png#mediaviewer/ File:Ieacid2.png i67acid2.png "Ie7acid2" by Acid2 Task Force - https:// commons.wikimedia.org/wiki/File:Ie7acid2.png#mediaviewer/