The Talk youve been .await-ing for @steveklabnik async fn foo(s: - - PowerPoint PPT Presentation

the talk you ve been await ing for
SMART_READER_LITE
LIVE PREVIEW

The Talk youve been .await-ing for @steveklabnik async fn foo(s: - - PowerPoint PPT Presentation

The Talk youve been .await-ing for @steveklabnik async fn foo(s: String) -> i32 { // } fn foo(s: String) -> impl Future<Output=i32> { // } Stuff were going to talk about async/await and Futures Generators:


slide-1
SLIDE 1

The Talk you’ve been .await-ing for

@steveklabnik

slide-2
SLIDE 2
slide-3
SLIDE 3
slide-4
SLIDE 4
slide-5
SLIDE 5

async fn foo(s: String) -> i32 { // … } fn foo(s: String) -> impl Future<Output=i32> { // … }

slide-6
SLIDE 6

Stuff we’re going to talk about

  • async/await and Futures
  • Generators: the secret sauce
  • Tasks, Executors, & Reactors, oh my!
  • … maybe async fn in traits
slide-7
SLIDE 7

async/await and Futures

slide-8
SLIDE 8
slide-9
SLIDE 9
slide-10
SLIDE 10
slide-11
SLIDE 11
slide-12
SLIDE 12
slide-13
SLIDE 13

Async/await is simpler syntax for Futures

slide-14
SLIDE 14

Async/await is simpler syntax for Futures*

slide-15
SLIDE 15

A Future represents a value that will exist sometime in the future

slide-16
SLIDE 16

Let’s build a future!

slide-17
SLIDE 17

A timer future

  • Mutex around a boolean
  • Spins up a new thread that sleeps for some

amount of time

  • When the thread wakes up, it sets the boolean to

true and ‘wakes up’ the future

  • Calls to poll check the boolean to see if we’re

done

slide-18
SLIDE 18
slide-19
SLIDE 19
slide-20
SLIDE 20
slide-21
SLIDE 21
slide-22
SLIDE 22

Four rules

For using async/await

slide-23
SLIDE 23

async fn foo(s: String) -> i32 { // … } fn foo(s: String) -> impl Future<Output=i32> { // … }

slide-24
SLIDE 24

If you have a Future<Output=i32> and you want an i32, use .await on it

slide-25
SLIDE 25

You can only .await inside of an async fn or block

slide-26
SLIDE 26

To start executing a Future, you pass it to an executor

slide-27
SLIDE 27
slide-28
SLIDE 28
slide-29
SLIDE 29
slide-30
SLIDE 30

Generators aka stackless coroutines

slide-31
SLIDE 31

Generators are not stable … yet

slide-32
SLIDE 32
slide-33
SLIDE 33
slide-34
SLIDE 34
slide-35
SLIDE 35

Futures need to have poll() called over and

  • ver until a value is produced

Generators let you call yield over and over to get values async/await is a simpler syntax for a generator that implements the Future trait

slide-36
SLIDE 36

Tasks, Executors, & Reactors

slide-37
SLIDE 37

“The event loop”

slide-38
SLIDE 38

Task: a unit of work to execute, a chain of Futures Executor: schedules tasks Reactor: notifies the executor that tasks are ready to execute

slide-39
SLIDE 39

Interface to the reactor Executor calls poll, and provides a context

slide-40
SLIDE 40

Let’s build an executor!

slide-41
SLIDE 41

async fn foo() { // … }

slide-42
SLIDE 42

async fn foo() { // … } spawner.spawn(foo())

slide-43
SLIDE 43

async fn foo() { // … } spawner.spawn(foo()) Executor task queue

slide-44
SLIDE 44

async fn foo() { // … } spawner.spawn(foo()) Executor task queue

Calls poll() on the Future

slide-45
SLIDE 45

async fn foo() { // … } spawner.spawn(foo()) Executor task queue

Calls poll() on the Future

slide-46
SLIDE 46

async fn foo() { // … } spawner.spawn(foo()) Executor task queue

Calls poll() on the Future

Future calls wake() (reactor)

slide-47
SLIDE 47

async fn foo() { // … } spawner.spawn(foo()) Executor task queue

Calls poll() on the Future

Future calls wake() (reactor)

slide-48
SLIDE 48
slide-49
SLIDE 49
slide-50
SLIDE 50
slide-51
SLIDE 51
slide-52
SLIDE 52
slide-53
SLIDE 53
slide-54
SLIDE 54

A quick aside about Pin<P>

slide-55
SLIDE 55

Before a future starts executing, we need to be able to move it around in memory. (For example, to create a task out of it, we need to move it to the heap) Once a future starts executing, it must not move in memory. (otherwise, borrows in the body of the future would become invalid)

slide-56
SLIDE 56

When you turn some sort of pointer type into a Pin<P>, you’re promising that what the pointer to will no longer move. Box<T> turns into Pin<Box<T>> There’s an extra trait, “Unpin”, that says “I don’t care about this”, similar to how Copy says “I don’t care about move semantics.

slide-57
SLIDE 57

Let’s build a reactor!

slide-58
SLIDE 58

(We’re not gonna build a reactor)

slide-59
SLIDE 59

(We technically did build a reactor)

slide-60
SLIDE 60

Bonus round: async fn in traits

slide-61
SLIDE 61
slide-62
SLIDE 62

A function is only one function A trait is implemented for many types, and so is many functions

slide-63
SLIDE 63
slide-64
SLIDE 64
slide-65
SLIDE 65

It gets way more complicated

slide-66
SLIDE 66
slide-67
SLIDE 67
slide-68
SLIDE 68
slide-69
SLIDE 69

It gets way way way more complicated

slide-70
SLIDE 70
slide-71
SLIDE 71
slide-72
SLIDE 72
slide-73
SLIDE 73

Thanks!

@steveklabnik

  • https://rust-lang.github.io/async-book
  • https://tmandry.gitlab.io/blog/posts/optimizing-await-
1/
  • https://smallcultfollowing.com/babysteps/blog/2019/
10/26/async-fn-in-traits-are-hard/