Aaron Turon Mozilla Research C/C++ ML/Haskell Rust Safe - - PowerPoint PPT Presentation

aaron turon mozilla research c c ml haskell rust
SMART_READER_LITE
LIVE PREVIEW

Aaron Turon Mozilla Research C/C++ ML/Haskell Rust Safe - - PowerPoint PPT Presentation

Aaron Turon Mozilla Research C/C++ ML/Haskell Rust Safe systems programming Why Mozilla? Browsers need control . Browsers need safety . Servo: Next-generation browser built in Rust. C++ What is control? void example() {


slide-1
SLIDE 1

Aaron Turon Mozilla Research

slide-2
SLIDE 2

Rust C/C++ … ML/Haskell

Safe systems programming

slide-3
SLIDE 3

Why Mozilla?

Browsers need control. Browsers need safety. Servo: Next-generation browser built in Rust.

slide-4
SLIDE 4

What is control?

void example() { vector<string> vector; … auto& elem = vector[0]; … }

C++

slide-5
SLIDE 5

What is control?

void example() { vector<string> vector; … auto& elem = vector[0]; … } string [0] … vector data length capacity [0] [n] […] …

Stack and inline layout. Stack Heap

C++

slide-6
SLIDE 6

What is control?

void example() { vector<string> vector; … auto& elem = vector[0]; … } string [0] … vector data length capacity [0] [n] […] … ‘H’ … ‘e’

Stack and inline layout. Stack Heap

C++

slide-7
SLIDE 7

What is control?

void example() { vector<string> vector; … auto& elem = vector[0]; … } string [0] … vector data length capacity [0] [n] […] …

Stack and inline layout. Stack Heap

C++

slide-8
SLIDE 8

What is control?

void example() { vector<string> vector; … auto& elem = vector[0]; … } string [0] elem vector data length capacity [0] [n] […] …

Stack and inline layout. Lightweight references Stack Heap

C++

slide-9
SLIDE 9

What is control?

void example() { vector<string> vector; … auto& elem = vector[0]; … } string [0] elem vector data length capacity [0] [n] […] …

Stack and inline layout. Lightweight references Deterministic destruction Stack Heap

C++

slide-10
SLIDE 10

Zero-cost abstraction

Ability to define abstractions that

  • ptimize away to nothing.
slide-11
SLIDE 11

Zero-cost abstraction

Ability to define abstractions that

  • ptimize away to nothing.

vector data length cap. [0] […] data cap. ‘H’ ‘e’ […]

Java

slide-12
SLIDE 12

Zero-cost abstraction

Ability to define abstractions that

  • ptimize away to nothing.

vector data length cap. [0] […] data cap. ‘H’ ‘e’ […]

Not just memory layout:

  • Static dispatch
  • Template expansion

Java

slide-13
SLIDE 13

Zero-cost abstraction

Ability to define abstractions that

  • ptimize away to nothing.

vector data length cap. [0] […] data cap. ‘H’ ‘e’ […]

Not just memory layout:

  • Static dispatch
  • Template expansion

Java

safe

slide-14
SLIDE 14

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … elem

C++

slide-15
SLIDE 15

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … elem

C++

slide-16
SLIDE 16

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem

C++

slide-17
SLIDE 17

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem

C++

slide-18
SLIDE 18

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem

Dangling pointer: pointer to freed memory.

C++

slide-19
SLIDE 19

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem

Dangling pointer: pointer to freed memory.

C++

slide-20
SLIDE 20

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem

C++

slide-21
SLIDE 21

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem

Aliasing: more than

  • ne pointer to same

memory.

C++

slide-22
SLIDE 22

What is safety?

void example() { vector<string> vector; … auto& elem = vector[0]; vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem

Aliasing: more than

  • ne pointer to same

memory.

C++

Mutating the vector freed old contents.

slide-23
SLIDE 23

What about GC?

slide-24
SLIDE 24

What about GC?

No control. Requires a runtime.

slide-25
SLIDE 25

What about GC?

No control. Requires a runtime. Insufficient to prevent related problems: iterator invalidation, data races.

slide-26
SLIDE 26

Rust’s Solution

Type system enforces ownership and borrowing:

  • 1. All resources have a clear owner.
  • 2. Others can borrow from the owner.
  • 3. Owner cannot free or mutate the

resource while it is borrowed.

8

slide-27
SLIDE 27

Ownership/Borrowing

Memory safety Data-race freedom No need for a runtime

9

slide-28
SLIDE 28

Ownership/Borrowing

Memory safety Data-race freedom No need for a runtime C++

9

slide-29
SLIDE 29

Ownership/Borrowing

Memory safety Data-race freedom No need for a runtime GC C++

9

slide-30
SLIDE 30

More to Rust than Safety

Explicit control is often correlated with painfully verbose.

  • Rust offers lots of goodies

traditionally associated with garbage- collected runtimes:

  • Closures
  • Pattern matching
  • Type inference
  • Traits
slide-31
SLIDE 31

Credit where it is due

Rust has an active, amazing community.

slide-32
SLIDE 32

Ownership

  • n. The act, state, or right of possessing something.
slide-33
SLIDE 33

Ownership (T)

slide-34
SLIDE 34

Ownership (T)

slide-35
SLIDE 35

Ownership (T)

slide-36
SLIDE 36

Ownership (T)

slide-37
SLIDE 37

Ownership (T)

Aliasing Mutation

slide-38
SLIDE 38

Ownership (T)

Aliasing Mutation

slide-39
SLIDE 39

vec data length capacity vec data length capacity fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } fn take(vec: Vec<int>) { // … }

slide-40
SLIDE 40

vec data length capacity vec data length capacity fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } fn take(vec: Vec<int>) { // … }

slide-41
SLIDE 41

vec data length capacity vec data length capacity 1 fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } fn take(vec: Vec<int>) { // … }

slide-42
SLIDE 42

vec data length capacity vec data length capacity 1 fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } fn take(vec: Vec<int>) { // … }

slide-43
SLIDE 43

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<int>) { // … }

slide-44
SLIDE 44

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<int>) { // … }

slide-45
SLIDE 45

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<int>) { // … }

  • Take ownership
  • f a Vec<int>
slide-46
SLIDE 46

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<int>) { // … }

slide-47
SLIDE 47

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<int>) { // … }

slide-48
SLIDE 48

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<int>) { // … }

slide-49
SLIDE 49

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<int>) { // … }

slide-50
SLIDE 50

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<int>) { // … }

slide-51
SLIDE 51

vec data length capacity fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } fn take(vec: Vec<int>) { // … }

slide-52
SLIDE 52

vec data length capacity fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } fn take(vec: Vec<int>) { // … }

slide-53
SLIDE 53

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

Compiler enforces moves

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

slide-54
SLIDE 54

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

Compiler enforces moves

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

slide-55
SLIDE 55

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<int>) { // … }

slide-56
SLIDE 56

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<int>) { // … }

  • Error: vec has been moved
slide-57
SLIDE 57

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<int>) { // … }

  • Error: vec has been moved
slide-58
SLIDE 58

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<int>) { // … }

  • Error: vec has been moved

Prevents:

  • use after free
  • double moves
slide-59
SLIDE 59

Borrow

  • v. To receive something with the promise of returning it.
slide-60
SLIDE 60

Shared borrow (&T)

slide-61
SLIDE 61

Shared borrow (&T)

slide-62
SLIDE 62

Shared borrow (&T)

slide-63
SLIDE 63

Shared borrow (&T)

Aliasing Mutation

slide-64
SLIDE 64

Shared borrow (&T)

Aliasing Mutation

slide-65
SLIDE 65

Mutable borrow (&mut T)

slide-66
SLIDE 66

Mutable borrow (&mut T)

slide-67
SLIDE 67

Mutable borrow (&mut T)

slide-68
SLIDE 68

Mutable borrow (&mut T)

slide-69
SLIDE 69

Mutable borrow (&mut T)

slide-70
SLIDE 70

Mutable borrow (&mut T)

slide-71
SLIDE 71

Mutable borrow (&mut T)

slide-72
SLIDE 72

Mutable borrow (&mut T)

Aliasing Mutation

slide-73
SLIDE 73

Mutable borrow (&mut T)

Aliasing Mutation

slide-74
SLIDE 74

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

slide-75
SLIDE 75

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity

slide-76
SLIDE 76

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity

slide-77
SLIDE 77

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity

“Shared reference to Vec<int>”

slide-78
SLIDE 78

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity

“Shared reference to Vec<int>” Loan out vec

slide-79
SLIDE 79

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity vec

“Shared reference to Vec<int>” Loan out vec

slide-80
SLIDE 80

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity vec

slide-81
SLIDE 81

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity vec

slide-82
SLIDE 82

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity

slide-83
SLIDE 83

fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); use(&vec); … } fn use(vec: &Vec<int>) { // … }

  • 1

2 vec data length capacity

slide-84
SLIDE 84

fn use(vec: &Vec<int>) { vec.push(3); vec[1] += 2; }

Shared references are immutable:

Aliasing Mutation

slide-85
SLIDE 85

fn use(vec: &Vec<int>) { vec.push(3); vec[1] += 2; }

Shared references are immutable:

Aliasing Mutation

slide-86
SLIDE 86

fn use(vec: &Vec<int>) { vec.push(3); vec[1] += 2; }

Shared references are immutable:

Aliasing Mutation

slide-87
SLIDE 87

fn use(vec: &Vec<int>) { vec.push(3); vec[1] += 2; }

Shared references are immutable: Error: cannot mutate shared reference

Aliasing Mutation

slide-88
SLIDE 88

fn use(vec: &Vec<int>) { vec.push(3); vec[1] += 2; }

Shared references are immutable: Error: cannot mutate shared reference

* Actually: mutation only in controlled circumstances

*

Aliasing Mutation

slide-89
SLIDE 89

fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

Mutable references

slide-90
SLIDE 90

fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

Mutable references

mutable reference to Vec<int>

slide-91
SLIDE 91

fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

Mutable references

mutable reference to Vec<int> push() is legal

slide-92
SLIDE 92

Efficient Iteration

1 2 3 from to … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-93
SLIDE 93

Efficient Iteration

1 2 3 from to … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-94
SLIDE 94

Efficient Iteration

1 2 3 from to elem … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-95
SLIDE 95

Efficient Iteration

1 2 3 from to elem … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-96
SLIDE 96

Efficient Iteration

1 2 3 from to elem 1 … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-97
SLIDE 97

Efficient Iteration

1 2 3 from to elem 1 … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-98
SLIDE 98

Efficient Iteration

1 2 3 from to elem 1 … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-99
SLIDE 99

What if from and to are equal?

1 2 3 from to elem … fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-100
SLIDE 100

What if from and to are equal?

1 2 3 from to elem 1 2 3 … 1 fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-101
SLIDE 101

What if from and to are equal?

1 2 3 from to elem 1 2 3 … 1 fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

slide-102
SLIDE 102

What if from and to are equal?

1 2 3 from to elem 1 2 3 … 1 fn push_all(from: &Vec<int>, to: &mut Vec<int>) { for elem in from.iter() { to.push(*elem); } }

dangling pointer

slide-103
SLIDE 103

fn push_all(from: &Vec<int>, to: &mut Vec<int>) {…}

  • fn caller() {

let mut vec = …; push_all(&vec, &mut vec); }

slide-104
SLIDE 104

fn push_all(from: &Vec<int>, to: &mut Vec<int>) {…}

  • fn caller() {

let mut vec = …; push_all(&vec, &mut vec); }

shared reference

slide-105
SLIDE 105

fn push_all(from: &Vec<int>, to: &mut Vec<int>) {…}

  • fn caller() {

let mut vec = …; push_all(&vec, &mut vec); }

shared reference Error: cannot have both shared and mutable reference at same time

slide-106
SLIDE 106

fn push_all(from: &Vec<int>, to: &mut Vec<int>) {…}

  • fn caller() {

let mut vec = …; push_all(&vec, &mut vec); }

shared reference Error: cannot have both shared and mutable reference at same time

slide-107
SLIDE 107

fn push_all(from: &Vec<int>, to: &mut Vec<int>) {…}

  • fn caller() {

let mut vec = …; push_all(&vec, &mut vec); }

shared reference Error: cannot have both shared and mutable reference at same time A &mut T is the only way to access the memory it points at

slide-108
SLIDE 108

{ let mut vec = Vec::new(); … for i in range(0, vec.len()) { let elem: &int = &vec[i]; … vec.push(…); } … vec.push(…); }

Borrows restrict access to the original path for their duration. & &mut no writes, no moves no access at all

slide-109
SLIDE 109

{ let mut vec = Vec::new(); … for i in range(0, vec.len()) { let elem: &int = &vec[i]; … vec.push(…); } … vec.push(…); }

Borrows restrict access to the original path for their duration. & &mut no writes, no moves no access at all

slide-110
SLIDE 110

{ let mut vec = Vec::new(); … for i in range(0, vec.len()) { let elem: &int = &vec[i]; … vec.push(…); } … vec.push(…); }

Borrows restrict access to the original path for their duration. & &mut no writes, no moves no access at all

slide-111
SLIDE 111

{ let mut vec = Vec::new(); … for i in range(0, vec.len()) { let elem: &int = &vec[i]; … vec.push(…); } … vec.push(…); }

Borrows restrict access to the original path for their duration. Error: vec[i] is borrowed, cannot mutate & &mut no writes, no moves no access at all

slide-112
SLIDE 112

{ let mut vec = Vec::new(); … for i in range(0, vec.len()) { let elem: &int = &vec[i]; … vec.push(…); } … vec.push(…); }

Borrows restrict access to the original path for their duration. Error: vec[i] is borrowed, cannot mutate

  • OK. loan expired.

& &mut no writes, no moves no access at all

slide-113
SLIDE 113

Concurrency

  • n. several computations executing simultaneously, and

potentially interacting with each other

slide-114
SLIDE 114

Data race

Two unsynchronized threads accessing same data where at least one writes.

✎ ✎

slide-115
SLIDE 115

Data race

Two unsynchronized threads accessing same data where at least one writes.

✎ ✎

slide-116
SLIDE 116

Aliasing Mutation No ordering Data race

slide-117
SLIDE 117

Aliasing Mutation No ordering Data race

Sound familiar?

slide-118
SLIDE 118

Actors—forbid aliasing Functional—forbid mutation Rust—forbid both from

  • ccurring simultaneously
slide-119
SLIDE 119

Messaging

(ownership)

slide-120
SLIDE 120

Messaging

(ownership)

slide-121
SLIDE 121

Messaging

(ownership)

slide-122
SLIDE 122

Messaging

(ownership)

slide-123
SLIDE 123

Messaging

(ownership)

slide-124
SLIDE 124

fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-125
SLIDE 125

rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-126
SLIDE 126

rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-127
SLIDE 127

rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-128
SLIDE 128

move || { let m = Vec::new(); … tx.send(m); } rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-129
SLIDE 129

move || { let m = Vec::new(); … tx.send(m); } rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-130
SLIDE 130

move || { let m = Vec::new(); … tx.send(m); } rx tx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-131
SLIDE 131

move || { let m = Vec::new(); … tx.send(m); } rx tx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-132
SLIDE 132

data length capacity data length capacity move || { let m = Vec::new(); … tx.send(m); } rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-133
SLIDE 133

data length capacity data length capacity move || { let m = Vec::new(); … tx.send(m); } rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-134
SLIDE 134

data length capacity data length capacity move || { let m = Vec::new(); … tx.send(m); } rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-135
SLIDE 135

data length capacity data length capacity move || { let m = Vec::new(); … tx.send(m); } rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-136
SLIDE 136

data length capacity data length capacity move || { let m = Vec::new(); … tx.send(m); } rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv(); }

slide-137
SLIDE 137

Shared read-only access

(ownership, borrowing)

slide-138
SLIDE 138

Arc<Vec<int>>

ref_count data length capacity [0] [1]

slide-139
SLIDE 139

Arc<Vec<int>>

ref_count data length capacity [0] [1]

(ARC = Atomic Reference Count)

slide-140
SLIDE 140

Arc<Vec<int>>

ref_count data length capacity [0] [1]

Vec<int>

(ARC = Atomic Reference Count)

slide-141
SLIDE 141

Arc<Vec<int>>

ref_count data length capacity [0] [1]

Vec<int>

Owned, so no aliases. (ARC = Atomic Reference Count)

slide-142
SLIDE 142

Arc<Vec<int>> &Vec<int>

ref_count data length capacity [0] [1]

Vec<int>

Owned, so no aliases. (ARC = Atomic Reference Count)

slide-143
SLIDE 143

Arc<Vec<int>> &Vec<int>

ref_count data length capacity [0] [1]

Shared reference, so Vec<int> is immutable.

Vec<int>

Owned, so no aliases. (ARC = Atomic Reference Count)

slide-144
SLIDE 144

fn send<T: Send>(&self, t: T)

Only “sendable” types

Thread safety checking

slide-145
SLIDE 145

Arc<Vec<int>>: Send Rc<Vec<int>> : !Send fn send<T: Send>(&self, t: T)

Only “sendable” types

Thread safety checking

slide-146
SLIDE 146

Locked mutable access

(ownership, borrowing)

✎ ✎

slide-147
SLIDE 147

fn sync_inc(mutex: &Mutex<int>) { let mut data = mutex.lock(); *data += 1; }

slide-148
SLIDE 148

fn sync_inc(mutex: &Mutex<int>) { let mut data = mutex.lock(); *data += 1; }

slide-149
SLIDE 149

fn sync_inc(mutex: &Mutex<int>) { let mut data = mutex.lock(); *data += 1; }

Destructor releases lock

slide-150
SLIDE 150

fn sync_inc(mutex: &Mutex<int>) { let mut data = mutex.lock(); *data += 1; }

Destructor releases lock Yields a mutable reference to data

slide-151
SLIDE 151

fn sync_inc(mutex: &Mutex<int>) { let mut data = mutex.lock(); *data += 1; }

Destructor releases lock Yields a mutable reference to data Destructor runs here, releasing lock

slide-152
SLIDE 152

Parallel

  • adj. occurring or existing at the same time
slide-153
SLIDE 153

fn qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); qsort(less); qsort(greater); } [0] [1] [2] [3] […] [n]

slide-154
SLIDE 154

fn qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); qsort(less); qsort(greater); } [0] [1] [2] [3] […] [n] let vec: &mut [int] = …;

slide-155
SLIDE 155

fn qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); qsort(less); qsort(greater); } [0] [1] [2] [3] […] [n] let vec: &mut [int] = …;

slide-156
SLIDE 156

fn qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); qsort(less); qsort(greater); } [0] [1] [2] [3] […] [n] let vec: &mut [int] = …;

slide-157
SLIDE 157

fn qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); qsort(less); qsort(greater); } [0] [1] [2] [3] […] [n] let vec: &mut [int] = …;

slide-158
SLIDE 158

fn qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); qsort(less); qsort(greater); } [0] [1] [2] [3] […] [n] let vec: &mut [int] = …; less greater

slide-159
SLIDE 159

fn qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); qsort(less); qsort(greater); } [0] [1] [2] [3] […] [n] let vec: &mut [int] = …; less greater

slide-160
SLIDE 160

[0] [1] [2] [3] […] [n] let vec: &mut [int] = …; fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); parallel::join( || parallel_qsort(less), || parallel_qsort(greater) ); }

slide-161
SLIDE 161

[0] [1] [2] [3] […] [n] let vec: &mut [int] = …; fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); parallel::join( || parallel_qsort(less), || parallel_qsort(greater) ); }

slide-162
SLIDE 162

[0] [1] [2] [3] […] [n] let vec: &mut [int] = …; less greater fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); parallel::join( || parallel_qsort(less), || parallel_qsort(greater) ); }

slide-163
SLIDE 163

[0] [1] [2] [3] […] [n] let vec: &mut [int] = …; less greater fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); parallel::join( || parallel_qsort(less), || parallel_qsort(greater) ); }

slide-164
SLIDE 164

[0] [1] [2] [3] […] [n] let vec: &mut [int] = …; less greater fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); parallel::join( || parallel_qsort(less), || parallel_qsort(greater) ); }

slide-165
SLIDE 165

[0] [1] [2] [3] […] [n] let vec: &mut [int] = …; less greater fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); parallel::join( || parallel_qsort(less), || parallel_qsort(greater) ); }

slide-166
SLIDE 166

And beyond…

Concurrency 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.
slide-167
SLIDE 167

And beyond…

Concurrency 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.

Always data-race free

slide-168
SLIDE 168

Unsafe

  • adj. not safe; hazardous
slide-169
SLIDE 169

Safe abstractions

unsafe { … }

  • Useful for:
  • Uninitialized memory
  • Interfacing with C code
  • Building parallel abstractions like ARC
  • Ownership/borrowing permit creating

safe abstraction boundaries.

slide-170
SLIDE 170

Safe abstractions

unsafe { … }

  • Useful for:
  • Uninitialized memory
  • Interfacing with C code
  • Building parallel abstractions like ARC
  • Ownership/borrowing permit creating

safe abstraction boundaries. Trust me.

slide-171
SLIDE 171

Safe abstractions

unsafe { … }

  • Useful for:
  • Uninitialized memory
  • Interfacing with C code
  • Building parallel abstractions like ARC
  • Ownership/borrowing permit creating

safe abstraction boundaries. Trust me.

fn something_safe(…) {

  • }
slide-172
SLIDE 172

Safe abstractions

unsafe { … }

  • Useful for:
  • Uninitialized memory
  • Interfacing with C code
  • Building parallel abstractions like ARC
  • Ownership/borrowing permit creating

safe abstraction boundaries. Trust me.

fn something_safe(…) {

  • }

Validates input, etc.

slide-173
SLIDE 173

Status of Rust

1.0 Beta: March 31st 1.0 Final: May 15th

  • Stable syntax, core type system
  • Basic standard library
  • Blossoming ecosystem on crates.io
  • Subsequent releases coming

every six weeks.

slide-174
SLIDE 174

Conclusions

  • Rust combines high-level features with low-level

control.

  • Rust gives strong safety guarantees beyond what

GC can offer:

  • Deterministic destruction
  • Data race freedom
  • Iterator invalidation