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.

Avatar for Alex Burkhart

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/