Async/.await

14 декември 2021

Паралелизъм и конкурентност

Кога искаме паралелизъм?

Кога искаме конкурентност?

Кога искаме конкурентност?

Модели за конкурентност

Kernel space

Модели за конкурентност

Kernel space

Модели за конкурентност

Kernel space

Модели за конкурентност

Kernel space

Модели за конкурентност

User space

Модели за конкурентност

User space

Модели за конкурентност

User space

Модели за конкурентност

User space

Асинхронно програмиране

1 2 3 4 5 6 7 8 9
async fn get_two_sites_async() {
    // Create two different "futures" which, when run to completion,
    // will asynchronously download the webpages.
    let future_one = download_async("https://www.foo.com");
    let future_two = download_async("https://www.bar.com");

    // Run both futures to completion at the same time.
    join!(future_one, future_two);
}

Асинхронно програмиране в Rust

Асинхронно програмиране в Rust

Асинхронно програмиране в Rust

Асинхронно програмиране в Rust

Асинхронно програмиране в Rust

Асинхронно програмиране в Rust

Библиотечни функции:

Изпълними програми:

Async/.await в Rust

async функции

1 2 3 4
// връща анонимен тип, който имплементира trait-а `Future<Output = u8>`
async fn five() -> u8 {
    5
}
#![allow(dead_code)]
// връща анонимен тип, който имплементира trait-а `Future`
async fn five() -> u8 {
    5
}
fn main() {}

Async/.await в Rust

async блокове

1 2 3 4 5 6 7 8 9
use std::future::Future;

fn ten() -> impl Future<Output = u8> {
    // връща анонимен тип, който имплементира trait-а `Future<Output = u8>`
    async {
        let x: u8 = five().await;
        x + 5
    }
}
#![allow(dead_code)]
use std::future::Future;

fn ten() -> impl Future {
    // връща анонимен тип, който имплементира trait-а `Future`
    async {
        let x: u8 = five().await;
        x + 5
    }
}
async fn five() -> u8 { 5 }
fn main() {}

Async/.await в Rust

.await

1 2 3 4 5 6 7 8 9 10 11
async fn five() -> u8 {
    5
}

async fn ten() -> u8 {
    five().await + 5
}

fn main() {
    let x = ten().await;
}
error[E0728]: `await` is only allowed inside `async` functions and blocks --> src/bin/main_c247aff303b227bd4f1fa2405d3f7ad357520e11.rs:10:13 | 9 | fn main() { | ---- this is not `async` 10 | let x = ten().await; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks For more information about this error, try `rustc --explain E0728`. error: could not compile `rust` due to previous error
async fn five() -> u8 {
    5
}

async fn ten() -> u8 {
    five().await + 5
}

fn main() {
    let x = ten().await;
}

Async/.await в Rust

.await

1 2 3 4 5 6 7 8 9 10 11 12 13
async fn five() -> u8 {
    5
}

async fn ten() -> u8 {
    five().await + 5
}

fn main() {
    let x = ::futures::executor::block_on(async {
        ten().await
    });
}
async fn five() -> u8 {
    5
}

async fn ten() -> u8 {
    five().await + 5
}

fn main() {
    let x = ::futures::executor::block_on(async {
        ten().await
    });
}

Trait Future

1 2 3 4 5 6 7 8 9 10
pub trait Future {
    type Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output>;
}

pub enum Poll<T> {
    Ready(T),
    Pending,
}
use std::task::Context;
use std::pin::Pin;

pub trait Future {
    type Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll;
}

pub enum Poll {
    Ready(T),
    Pending,
}

fn main() {}

Trait Future

1 2 3 4 5
async fn foo() {
    println!("foo");
}

let foo_future = foo();
#![allow(unused_variables)]
fn main() {
async fn foo() {
    println!("foo");
}

let foo_future = foo();
}

Изпълнение на future

Future може да се изпълни

Изпълнение на future

Futures извършват прогрес, когато някой executor им извика poll

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
fn main() {
    let fut1 = async_func1();
    ::futures::executor::block_on(fut1);
}

async fn async_func1() -> i32 {
    let fut2 = another_async_func();
    let x = fut2.await;

    let y = regular_func();

    let fut3 = make_call_to_db();
    let z = fut3.await;

    x + y
}

fn main() {
    let fut1 = async_func1();
    ::futures::executor::block_on(fut1);
}

async fn async_func1() -> i32 {
    let fut2 = another_async_func();
    let x = fut2.await;

    let y = regular_func();

    let fut3 = make_call_to_db();
    let z = fut3.await;

    x + y
}
async fn another_async_func() -> i32 { 0 }
async fn make_call_to_db() -> i32 { 0 }
fn regular_func() -> i32 { 0 }

Изпълнение на future

За да могат да се прекъсват, всички нужни локални променливи се запомнят във future-а.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
fn main() {
    let fut1 = async_func1();
    ::futures::executor::block_on(fut1);
}

async fn async_func1() -> i32 {
    let fut2 = another_async_func();
    let x = fut2.await;

    let y = regular_func();

    let fut3 = make_call_to_db();
    let z = fut3.await;

    x + y
}

fn main() {
    let fut1 = async_func1();
    ::futures::executor::block_on(fut1);
}

async fn async_func1() -> i32 {
    let fut2 = another_async_func();
    let x = fut2.await;

    let y = regular_func();

    let fut3 = make_call_to_db();
    let z = fut3.await;

    x + y
}
async fn another_async_func() -> i32 { 0 }
async fn make_call_to_db() -> i32 { 0 }
fn regular_func() -> i32 { 0 }

1 2 3 4 5
enum Fut1 {
    AtAwait1 { fut2: Fut2 },
    AtAwait2 { x: i32, y: i32, fut3: Fut3 },
    Done,
}

Futures екосистемата

Futures екосистемата

Futures екосистемата

Futures екосистемата

Futures екосистемата

Futures екосистемата

Futures екосистемата

Futures екосистемата

Съвместимост

Futures екосистемата

Съвместимост

Futures екосистемата

Съвместимост

Futures екосистемата

Съвместимост

Малък демо проект

Web crawler, който събира и напечатва линкове към блогове от https://this-week-in-rust.org

Използвани библиотеки

https://github.com/nikolads/rust_async_demo

Подводни камъни

Блокиращи операции

Подводни камъни

Блокиращи операции

Подводни камъни

Блокиращи операции

Подводни камъни

Блокиращи операции

Подводни камъни

Примитиви за синхронизация

Подводни камъни

Примитиви за синхронизация

Подводни камъни

Примитиви за синхронизация

Подводни камъни

Примитиви за синхронизация

Подводни камъни

Тежки операции

Подводни камъни

Тежки операции

Подводни камъни

Тежки операции

Подводни камъни

Тежки операции

Допълнителни материали

Въпроси