+ All Categories
Home > Science > Intro to Rust from Applicative / NY Meetup

Intro to Rust from Applicative / NY Meetup

Date post: 19-Jul-2015
Category:
Upload: nikomatsakis
View: 164 times
Download: 0 times
Share this document with a friend
Popular Tags:
29
Nicholas Matsakis Mozilla Research 1
Transcript

Nicholas Matsakis!Mozilla Research

1

So you want to start a project

Bugs!

C++?

Control!

Dangling pointers Double frees

Segmentation faults Data races…

2

What about GC?

No control.

Requires a runtime.

Insufficient to prevent related problems: resource management, data races.

3

Rust’s Solution

Type system enforces ownership and borrowing: !1. All memory has a clear owner. 2. Others can borrow from the owner. 3. Owner cannot free or mutate the

memory while it is borrowed.

4

Ownership/Borrowing

Memory safety

Data-race freedom

No need for a runtime

GCC++

5

Credit where it is due

Rust has an active, amazing community.

6

Ownership!!n. The act, state, or right of possessing something.

7

Ownership8

vec

data

length

capacity

vec

data

length

capacity

1

2

fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … }

fn take(vec: Vec<i32>) { // … } !!!

Take ownership of a Vec<i32>

9

fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } vec.push(2);

Compiler enforces moves

fn take(vec: Vec<i32>) { // … } !!!Error: vec has been moved

Prevents: - use after free - double moves - …

10

Borrow!!v. To receive something with the promise of returning it.

11

* Actually: mutation only in controlled circumstances

*

Shared borrow (&T)

Sharing Mutation

Mutable borrow (&mut T)13

Sharing Mutation

fn example() { let mut names = Vec::new(); names.push(..); names.push(..); let name = &names[1]; names.push(..); print(name); }

names

data

length

capacity

“brson”

“pcwalton”

name

“brson”

“pcwalton”

“acrichto”

Sharing: more than one pointer to same memory.

Dangling pointer: pointer to freed memory.

Mutating the vector freed old contents.

14

fn example() { let mut names = Vec::new(); names.push(..); names.push(..); let name = &names[1]; names.push(..); print(name); }

Borrow “locks” `names` until `name` goes out of scopeError: cannot mutate

`names` while borrowed

15

fn example() { let mut names = Vec::new(); names.push(..); names.push(..); while something-or-other { let name = &names[1]; … names.push(..); print(name); } names.push(..); }

Outside of borrow scope — OK.

Scope of borrow in this case covers only the loop body.

16

Parallel!!adj. occurring or existing at the same time

17

Data race

Two unsynchronized threads accessing same data!

where at least one writes.

✎ ✎18

Sharing

Mutation

No ordering

Data race

Sound familiar?

19

Double buffering

A B

A B

20

fn process(a: &mut Vec<i32>, b: &mut Vec<i32>) { while !done { computation(a, b); computation(b, a); } } !fn computation(input: &Vec<i32>, output: &mut Vec<i32>) { … }

Double buffering

Temporarily immutable

21

Double buffering in parallel

A B

A B

B

A

22

fn par_computation(input: &Vec<i32>, output: &mut Vec<i32>) { let len = output.len(); let (l, r) = output.split_at_mut(len/2); let left_thread = scoped(|| computation(input, l)); computation(input, r); left_thread.join(); }

Create two disjoint views

Start a “scoped” thread to process `l`Process `r` in the

main threadBlock until `left_thread` completes (implicit)

23

What about data races?

fn par_computation(input: &Vec<i32>, output: &mut Vec<i32>) { let len = output.len(); let (l, r) = output.split_at_mut(len/2); let left_thread = scoped(|| computation(input, l)); computation(input, l); left_thread.join(); }

Process `l` in both threads?

24

fn par_computation(input: &Vec<i32>, output: &mut Vec<i32>) { let len = output.len(); let (l, r) = output.split_at_mut(len/2); let left_thread = scoped(|| computation(input, l)); computation(input, l); left_thread.join(); }

Shared borrow of `input` — OK

Shared borrow of `input` Mutable borrow of `l`

Error: `l` is mutably borrowed, cannot access

25

And beyond…Parallelism is an area of active development.

!Either already have or have plans for: - Atomic primitives - Non-blocking queues - Concurrent hashtables - Lightweight thread pools - Futures - CILK-style fork-join concurrency - etc.

All “just libraries”. And all ensure data-race freedom.26

Unsafe!!adj. not safe; hazardous

27

Safe abstractions

unsafe { … }

• Useful for: • Uninitialized memory • Interfacing with C code • Building parallel abstractions

• Ownership/borrowing permit creating safe abstraction boundaries.

Trust me.

fn something_safe(…) { !!!!}

Validates input, etc.

28

Conclusions

• Rust combines high-level features with low-level control.

• Rust gives stronger safety guarantees than GC: • No null pointers • Data race freedom

29


Recommended