Share
Embed
The Cost of Ownership: Should You Rent or Buy?
My January Columbus Rust Society presentation on Rust's Ownership system.
Alex Burkhart
January 28, 2015
Transcript
29 slides
-
"The goal is to design and implement a safe, concurrent,
practical, static systems language." — Rust Project FAQ -
Strings fn greet(name: String) { println!("Hello {:?}!", name); } fn
main() { let person = "Alex"; greet(person); } -
Two String Types fn greet(name: String) { println!("Hello {:?}!", name);
} fn main() { let person: &str = "Alex"; greet(person); } -
Use the Right String fn greet(name: String) { println!("Hello {:?}!",
name); } fn main() { let person: String = "Alex".to_string(); greet(person); } -
String Slices fn greet(name: &str) { println!("Hello {:?}!", name); }
fn main() { let person: &str = "Alex"; greet(person); } -
Stack & Heap Memory #[derive(Debug)] enum Color { Red, Yellow,
Green, } fn main() { let stack: Color = Color::Red; let heap: Box<Color> = box Color::Green; println!("stack: {:?}, heap: {:?}", stack, heap); } -
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); } -
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 // implicit drop(owner); } -
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 } -
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 -
Strings Revisited fn greet(name: &str) { println!("Hello {:?}!", name); }
fn main() { let person: &'static str = "Alex"; greet(person); } -
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 } -
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 } -
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 } -
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! } -
When does it Move? enum Foo { F1, F2 }
impl Copy for Foo {} enum Bar { B1, B2 } // !Copy fn main() { let f = Foo::F1 let g = f; // copied let b = Bar::B1; let c = b; // moved } -
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 } -
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, } } -
Slices Revisited 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); } -
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 } -
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! }