concurrency in rust di… · alex crichton . must be this tall to write multi-threaded code. what...
TRANSCRIPT
![Page 1: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/1.jpg)
Concurrency in RustAlex Crichton
![Page 2: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/2.jpg)
![Page 3: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/3.jpg)
![Page 4: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/4.jpg)
Must bethis tall to write multi-threaded code.
![Page 5: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/5.jpg)
![Page 6: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/6.jpg)
What Rust has to offer
Strong safety guarantees…No seg-faults, no data-races, expressive type system.
…without compromising on performance.No garbage collector, no runtime.
Goal: Confident, productive systems programming
![Page 7: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/7.jpg)
Concurrency?
Libraries
Futures
Rust?
![Page 8: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/8.jpg)
What’s concurrency?
In computer science, concurrency is a property of systems in which several computations are executing simultaneously, and potentially interacting with each other.
![Page 9: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/9.jpg)
Getting our feet wet
// What does this print?int main() { int pid = fork(); printf("%d\n", pid);}
![Page 10: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/10.jpg)
Concurrency is hard!
• Data Races
• Race Conditions
• Deadlocks
• Use after free
• Double free
Exploitable!
![Page 11: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/11.jpg)
Concurrency is nice!
0
25
50
75
100
Amazon YouTube YouTube (32 bit)
![Page 12: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/12.jpg)
Concurrency?
Libraries
Futures
Rust?
![Page 13: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/13.jpg)
Zero-cost abstractions
Memory safety & data-race freedom
+
=Confident, productive systems programming
![Page 14: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/14.jpg)
What’s safety?void example() { vector<string> vector; // ... auto& elem = vector[0]; vector.push_back(some_string); cout << elem; }
elem
vector
...[0]
[0]
[1]
Dangling pointer!Aliased pointers
Mutation
![Page 15: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/15.jpg)
Rust’s SolutionOwnership/Borrowing
No runtime Memory Safety
No data races
C++ GC
![Page 16: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/16.jpg)
Ownershipfn main() { let mut v = Vec::new(); v.push(1); v.push(2); take(v); // ...}
fn take(v: Vec<i32>) { // ...}
vector
vector
1
2
![Page 17: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/17.jpg)
Ownershipfn main() { let mut v = Vec::new(); v.push(1); v.push(2); take(v); // ...}
fn take(v: Vec<i32>) { // ...}
![Page 18: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/18.jpg)
Ownershipfn main() { let mut v = Vec::new(); v.push(1); v.push(2); take(v); v.push(3);}
fn take(v: Vec<i32>) { // ...}
![Page 19: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/19.jpg)
Ownershipfn main() { let mut v = Vec::new(); v.push(1); v.push(2); take(v); v.push(3);}
fn take(v: Vec<i32>) { // ...}
error: use of moved value `v`
![Page 20: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/20.jpg)
Borrowingfn main() { let mut v = Vec::new(); push(&mut v); read(&v); // ...}
vector
fn push(v: &mut Vec<i32>) { v.push(1);}
v
1
fn read(v: &Vec<i32>) { // ...}
![Page 21: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/21.jpg)
Safety in Rust
• Rust statically prevents aliasing + mutation
• Ownership prevents double-free
• Borrowing prevents use-after-free
• Overall, no segfaults!
![Page 22: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/22.jpg)
Sharing
Mutation
No ordering
Data race
Sound familiar?
Data races
![Page 23: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/23.jpg)
Concurrency?
Libraries
Futures
Rust?
![Page 24: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/24.jpg)
Originally: Rust had message passing built into the language.
Now: library-based, multi-paradigm.
Libraries leverage ownership and borrowing to avoid data races.
Library-based concurrency
![Page 25: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/25.jpg)
std::thread
let loc = thread::spawn(|| { “world” }); println!(“Hello, {}!”, loc.join().unwrap());
![Page 26: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/26.jpg)
std::thread
let mut dst = Vec::new(); thread::spawn(move || { dst.push(3); });
dst.push(4);
error: use after move
![Page 27: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/27.jpg)
std::thread
let mut dst = Vec::new(); thread::spawn(|| { dst.push(3); });
dst.push(4);error: value doesn’t live long enough
![Page 28: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/28.jpg)
std::thread
let v = Rc::new(vec![1, 2, 3]); let v2 = v.clone(); thread::spawn(move || { println!(“{}”, v.len()); }); another_function(v2.clone());
error: Rc<T> can’t be sent across threads
![Page 29: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/29.jpg)
std::sync::Arc
let v = Arc::new(vec![1, 2]); let v2 = v.clone(); thread::spawn(move || { println!(“{}”, v.len()); }); another_function(&v2);
refcount: 1
1
2
refcount: 2
v
v2
refcount: 0
![Page 30: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/30.jpg)
std::sync::Arc
let v = Arc::new(vec![1, 2]); let v2 = v.clone(); thread::spawn(move || { v.push(3); }); another_function(&v2);
error: cannot mutate through shared reference
![Page 31: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/31.jpg)
0
fn sync_inc(counter: &Mutex<i32>) { let mut data: Guard<i32> = counter.lock(); *data += 1; }
counter
data
1
std::sync::Mutex
![Page 32: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/32.jpg)
std::sync::atomic::*
let number = AtomicUsize::new(10); let prev = number.fetch_add(1, SeqCst); assert_eq!(prev, 10); let prev = number.swap(2, SeqCst); assert_eq!(prev, 11); assert_eq!(number.load(SeqCst), 2);
![Page 33: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/33.jpg)
let (tx, rx) = mpsc::channel(); let tx2 = tx.clone(); thread::spawn(move || tx.send(5)); thread::spawn(move || tx2.send(4));
// Prints 4 and 5 in an unspecified order println!(“{:?}”, rx.recv()); println!(“{:?}”, rx.recv());
rx tx
std::sync::mpsc
4
5
tx2
![Page 34: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/34.jpg)
fn sum_of_squares(input: &[i32]) -> i32 { input.iter() .map(|&i| i * i) .sum() }
rayon
![Page 35: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/35.jpg)
use rayon::prelude::*;
fn sum_of_squares(input: &[i32]) -> i32 { input.par_iter() .map(|&i| i * i) .sum() }
rayon
![Page 36: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/36.jpg)
rayonuse rayon::prelude::*;
fn sum_of_squares(input: &[i32]) -> i32 { let mut cnt = 0; input.par_iter() .map(|&i| { cnt += 1; i * i }) .sum() } error: `cnt` cannot be shared concurrently
![Page 37: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/37.jpg)
crossbeam
• Epoch-based memory reclamation
• Easy translation of algorithms that require GC
• Work stealing deque
• MPMC queues
![Page 38: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/38.jpg)
100% Safe
• Everything you just saw is foolproof
• No segfaults
• No data races
• No double frees…
![Page 39: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/39.jpg)
Concurrency?
Libraries
Futures
Rust?
![Page 40: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/40.jpg)
Concurrent I/O
• Rust-the-language fuels shared-memory parallelism
• Rust-the-ecosystem fuels other forms of concurrency
• Futures are the core foundation for async I/O in Rust
![Page 41: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/41.jpg)
![Page 42: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/42.jpg)
What is async I/O?
// blocking let amt = socket.read(buffer);
assert_eq!(amt, 4);
// async let amt = socket.read(buffer); assert_eq!(amt, EWOULDBLOCK);
![Page 43: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/43.jpg)
What is async I/O?
• No I/O ever blocks
• Application receives bulk lists of events
• User responsible for dispatching events
![Page 44: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/44.jpg)
Async I/O can be hard
User: I’d like the contents of https://www.rust-lang.org, please!
Kernel: file descriptor 5 is ready for reading
![Page 45: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/45.jpg)
Futures
• Sentinel for a value “being computed”
• Internally captures state to produce a value
• Allows composing different kinds of computations
![Page 46: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/46.jpg)
Futures and async I/O
User: I’d like the contents of https://www.rust-lang.org, please!
Library: OK, here’s a Future<Vec<u8>>
![Page 47: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/47.jpg)
Futures without I/Olet result = pool.spawn(|| { fibonacci(100) });
println!(“calculating…”); get_some_coffee(); run_an_errand();
let result = result.wait(); println!(“fib(100) = {}”, result);
![Page 48: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/48.jpg)
Rust’s solution: Tokio
Tokio is the fusion of mio and futures
cross-platform async I/O
you can build futures with a TCP socket
![Page 49: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/49.jpg)
• Futures powered by TCP/UDP/…
• Works on all major platforms
• Implementation of an event loop
Rust’s solution: Tokio
![Page 50: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/50.jpg)
Futures today
• Traits for one value (Future), many values (Stream), or pushing values (Sink)
• “oneshot channels” - computing an in-memory value asynchronously
• “mpsc channels” - like std::sync::mpsc
• Integration with crates such as rayon
![Page 51: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/51.jpg)
Futures today#[async] fn fetch(client: hyper::Client, url: String) -> Result<Vec<u8>, hyper::Error> { let response = await!(client.get(&url)); if !response.status().is_ok() { return Err(…) } let mut body = Vec::new(); #[async] for chunk in response.body() { body.extend(chunk); } Ok(body) }
![Page 52: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/52.jpg)
Tokio today
• Crates such as tokio-core, tokio-proto, tokio-service
• Considering a tokio crate (tokio-rs/tokio-rfcs#2)
• Supports TCP, UDP, Unix sockets, Named pipes, processes, signals, HTTP, HTTP/2 (coming soon!), websockets, …
• Deployed to production in a number of companies
![Page 53: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/53.jpg)
Implementing Futures
struct Future<T> { // … }
What if I have a more efficient implementation?
![Page 54: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/54.jpg)
trait Future { type Item;
// ... }
![Page 55: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/55.jpg)
“A future is a sentinel for something being computed”
trait Future { type Item;
// ... }
![Page 56: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/56.jpg)
trait Future { type Item;
fn schedule<F>(self, F) where F: FnOnce(T); }
Can’t do virtual dispatch!
![Page 57: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/57.jpg)
fn compute(&self, key: u32) -> impl Future<Item=u32> { if let Some(v) = self.cache.get(&key) { future::ok(v) } else { self.compute_slow(key) } }
Different types!
![Page 58: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/58.jpg)
fn compute(&self, key: u32) -> impl Future<Item=u32> { if let Some(v) = self.cache.get(&key) { future::ok(v) } else { self.compute_slow(key) } }
![Page 59: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/59.jpg)
fn compute(&self, key: u32) -> impl Future<Item=u32> { if let Some(v) = self.cache.get(&key) { Either::A(future::ok(v)) } else { Either::B(self.compute_slow(key)) } }
Assuming:impl<A, B> Future for Either<A, B> where A: Future, B: Future
![Page 60: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/60.jpg)
fn compute(&self, key: u32) -> impl Future<Item=u32> { if let Some(v) = self.cache.get(&key) { Either::A(future::ok(v)) } else if ... { Either::B(self.compute_slow(key)) } else { // ... } }
Either::AA ?
![Page 61: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/61.jpg)
fn compute(&self, key: u32) -> Box<Future<Item=u32>> { if let Some(v) = self.cache.get(&key) { Box::new(future::ok(v)) } else if ... { Box::new(self.compute_slow(key)) } else { // ... } }
Virtual dispatch!
![Page 62: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/62.jpg)
trait Future { type Item;
fn schedule<F>(self, F) where F: FnOnce(T); }
Can’t do virtual dispatch!
![Page 63: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/63.jpg)
trait Future { type Item;
fn schedule(&mut self, f: Box<FnOnce(T)>); }
![Page 64: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/64.jpg)
trait Future { type Item;
fn schedule(&mut self, f: Box<FnOnce(T)>); }
![Page 65: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/65.jpg)
Servers as futures
fn process(req: Request) -> impl Future<Response> { // ... }
![Page 66: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/66.jpg)
Servers as futures
• Receive a request
• Load user from the database
• Query user’s GitHub username
• Look up username in database
• Render a response
Futures
![Page 67: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/67.jpg)
Servers as futuresGET /alex
SELECT gh_username FROM users WHERE login = ‘alex’
GET https://api.github.com/users/alexcrichton
SELECT * FROM crates WHERE gh_id = 64996
Render response
impl Future<Response>schedule()
schedule()
schedule()
schedule()
![Page 68: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/68.jpg)
Servers as futures
• Server responses may want to be entirely a future
• Futures are frequently composed of many futures
• Futures internally make many state transitions
• Each state transition is allocating a callback
![Page 69: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/69.jpg)
Futures and threading
trait Future { type Item;
fn schedule(&mut self, f: Box<FnOnce(T)>); }
Send? Sync?
![Page 70: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/70.jpg)
Drawbacks of callbacks
• Expensive at runtime, forced allocation per state transition
• Gymnastics with threading
• synchronization may be required where not necessary
• may require multiple “threadsafe future” and “non-threadsafe future” traits
![Page 71: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/71.jpg)
Constraints so far
• Futures must be a trait
• The Future trait must allow virtual dispatch
• State transitions need to be cheap
• Threadsafe futures shouldn’t require gymnastics
![Page 72: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/72.jpg)
GET /alex
SELECT gh_username FROM users WHERE login = ‘alex’
GET https://api.github.com/users/alexcrichton
SELECT * FROM crates WHERE gh_id = 64996
Render response
impl Future<Response>
![Page 73: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/73.jpg)
Read TCP connection Future<Response>
Decrypt SSL
Decode HTTP
Encode HTTP
Encrypt SSL
Write TCP connection Future<Response>
impl Future<Response>
Task
![Page 74: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/74.jpg)
Task TaskTask
Task Task Task
One Server
![Page 75: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/75.jpg)
Futures and Tasks
• A Task is composed of many futures
• All futures internal to a task track the same task
• Tasks are a unit of concurrency
• Very similar to green/lightweight threads!
![Page 76: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/76.jpg)
trait Future { type Item;
// … }
“A future is a sentinel for something being computed”
![Page 77: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/77.jpg)
trait Future { type Item;
fn poll(&mut self) -> Option<Self::Item>; }
![Page 78: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/78.jpg)
Poll-based futures
• A return value of None means “not ready”
• Returning Some resolves a future
• If you see None, when do you later call poll?
![Page 79: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/79.jpg)
Poll-based futures
• Futures are owned by one task
• If a future isn’t ready, the task needs to know when to try again
• A return value of None automatically means “I’ll notify you later”
![Page 80: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/80.jpg)
struct Timeout { // ... }
![Page 81: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/81.jpg)
struct Timeout { when: Instant, timer: Timer, }
// provided by another library impl Timer { fn defer(&self, at: Instant, f: impl FnOnce()) { // ... } }
When our timeout fires
Library support for this timeout
![Page 82: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/82.jpg)
impl Future for Timeout { type Item = ();
fn poll(&mut self) -> Option<()> { // ... } }
![Page 83: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/83.jpg)
impl Future for Timeout { type Item = ();
fn poll(&mut self) -> Option<()> { if self.when < Instant::now() { return Some(()) } // ... } }
![Page 84: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/84.jpg)
use futures::task;
impl Future for Timeout { type Item = ();
fn poll(&mut self) -> Option<()> { if self.when < Instant::now() { return Some(()) } let task = task::current(); self.timer.defer(self.when, || { task.notify(); }); None // not ready yet } }
![Page 85: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/85.jpg)
Constraints
• trait Future
• Virtual dispatch
• Cheap
• Threadsafe
trait Future { type Item;
fn poll(&mut self) -> Option<Self::Item>; }
![Page 86: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/86.jpg)
Constraints
• trait Future
• Virtual dispatch
• Cheap
• Threadsafe
mod task { fn current() -> Task { // just an Arc bump }
impl Task { fn notify(&self) { // just a queue } } }
![Page 87: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/87.jpg)
Constraints
• trait Future
• Virtual dispatch
• Cheap
• Threadsafe
fn assert<T: Send + Sync>() {}
assert::<Task>();
![Page 88: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/88.jpg)
I/O and Polling futures
• In Tokio everything is a future
• Futures may eventually need to wait for I/O
• Tokio’s job is to route I/O notifications to tasks
![Page 89: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/89.jpg)
I/O and Polling futures
// async let amt = socket.read(buffer); assert_eq!(amt, EWOULDBLOCK);
• I/O all returns immediately
• “would block” turns into notifying a task
• “would block” translated to NotReady
![Page 90: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/90.jpg)
I/O and Polling futures
trait AsyncRead: Read { // empty! }
trait AsyncWrite: Write { fn shutdown(&mut self) -> Poll<(), io::Error>; }
Marker traits for the current future’s task is scheduled to receive a notification when the object is ready again
![Page 91: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/91.jpg)
I/O and Polling futuresimpl<E: Read> Read for PollEvented<E>{ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { if self.poll_read().is_not_ready() { return Err(wouldblock()) } let r = self.get_mut().read(buf); if is_wouldblock(&r) { self.need_read(); } return r } }
![Page 92: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/92.jpg)
Tokio’s Event Loop
Kernel: file descriptor 5 is ready for reading
Tokio: Ok, let me go wake up that task.
![Page 93: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/93.jpg)
Tokio’s Event Loop
• Responsible for blocking the current thread
• Dispatches events received from the kernel
• Translates I/O notifications to task notifications
![Page 94: Concurrency in Rust di… · Alex Crichton . Must be this tall to write multi-threaded code. What Rust has to offer ... [1] Dangling pointer! Aliased pointers Mutation. Rust’s Solution](https://reader034.vdocuments.us/reader034/viewer/2022042622/5faaf941a4e83775c85b3a6c/html5/thumbnails/94.jpg)
users.rust-lang.org
doc.rust-lang.org/stable/book
github.com/alexcrichton/futures-rs