[0]

Rust의 비동기 프로그래밍을 위한 async/await 키워드와 Future trait에 대해 알아본다. 

 

[1]

Rust는 async/await, 그리고 이와 관련한 Future trait을 통해 비동기를 지원한다. 다음과 같이 간단히 사용할 수 있다. Future는 trait으로 다음과 같은 간단히 선언되어 있다. 

pub trait Future {
    type Output;

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

trait 자체는 Output type과 poll메소드로 매우 간단하다. poll에서는 Context라는 구조체를 변수로 받는데, 이에 대해서는 나중에 설명하도록 하겠다. async 키워드를 이용해 다음과 같이 Future trait object를 만들 수 있다.

async fn worker(){
    println!("this is worker!");
}

async{
    println("this is anonymous async!")
}

함수 선언에 async 키워드를 붙이거나, async 블록을 이용해서도 Future object를 만들 수 있다. 이 코드들은 일반적인 방식으로는 실행할 수 없다. 예를 들어 worker()로 호출하더라도 아무 의미 없는 구문일 뿐이다. 이를 실행하기 위해서는 await을 사용해야 한다. 

async fn worker(){
    println!("this is worker!");
}

fn main() {
    worker().await;
}

error[E0728]: `await` is only allowed inside `async` functions and blocks
  --> src\main.rs:10:5
   |
5  | fn main() {
   |    ---- this is not `async`
...
10 |     worker().await;
   |     ^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error: aborting due to previous error

하지만 Future object에 무작정 await를 하면 위와 같이 await는 async 블록 내에서만 사용할 수 있다는 에러가 발생한다. 그럼 main을 async로 바꿔보자.

error[E0752]: `main` function is not allowed to be `async`
 --> src\main.rs:5:1
  |
5 | async fn main() {
  | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`

error: aborting due to 2 previous errors

main은 async로 선언할 수 없다는 에러를 뱉는다. 그럼 임의로 async 블록을 만들고 그 안에서 await해보자.

async fn worker(){
    println!("this is worker!");
}

fn main() {
    async{
        worker().await;
    };
}

 

위와 같은 코드는 컴파일 가능하지만, "this is worker"가 출력되지는 않는다. main 내의 async블록이 await되지 않았기 때문이다. 정리해보자면 await를 하기 위해선 async 내부여야 하고, main은 async로 선언될 수 없다. 따라서 main이 아닌 최상위의 async 블록이 필요한데, 그 최상위의 async를 실행시킬 수가 없다! 이를 해결하기 위해서는 별도의 executor가 필요하다.

 

[2]

여기에서는 가장 널리 사용되는 tokio를 사용하겠다. 

use tokio::prelude::*;

async fn worker(){
    println!("this is worker!");
}

#[tokio::main]
async fn main() {
    worker().await;
    tokio::task::spawn(worker());
}

 

Cargo.toml에 tokio를 full feature로 포함시키면 위의 코드를 실행시킬 수 있다. worker().await또는 직접 task::spawn()을 사용하여 async 블록을 실행할 수 있다. 하지만 tokio는 꽤나 복잡하기 때문에 async가 어떻게 돌아가는지 알기는 다소 어렵다. 다음 포스팅에서 executor를 직접 구현하면서 async의 동작에 대해 알아보자. 

 

[참고]

https://rust-lang.github.io/async-book/

 

Getting Started - Asynchronous Programming in Rust

Welcome to Asynchronous Programming in Rust! If you're looking to start writing asynchronous Rust code, you've come to the right place. Whether you're building a web server, a database, or an operating system, this book will show you how to use Rust's asyn

rust-lang.github.io

 

'Computer Science > Rust' 카테고리의 다른 글

Unsafe Rust  (0) 2020.09.27
Rust의 trait object  (0) 2020.08.02
Rust의 Copy trait와 Clone trait  (2) 2020.06.30
Rust의 스마트 포인터  (0) 2020.05.20
Rust의 lifetime parameter  (0) 2020.05.05

20.07.11 ~ 07.18 (8일)

219쪽

 

다자이 오사무는 천재적인 작가다. 인간 실격처럼 노골적으로 자전적인 내용은 없지만, 전후에 몰락한 귀족의 모습을 아주 절절하게 그려냈다. 주인공과, 어머니, 그리도 남동생이 3인의 인물상도 상당히 흥미로우며, 전개도 지루하지 않게 흘러간다. 그리고 소설 전반적인 분위기도 굉장히 마음에 든다. 글로 표현하기는 약간 어렵지만, 전반적으로 대단히 훌륭한 작품이다.

20.06.20 ~ 07.10 (21일)

376쪽

 

책 제목만 보고 인플루엔자나 페스트같은 질병에 초점을 맞춘 책이라고 생각했지만, 그 보다는 권력자들의 질병에 대해 다룬 책에 가깝다. 대체로 시간 순서대로 권력자와 앓은 질병을 소개한다. 각 챕터의 분량이 적절해서 나눠 읽기에 좋지만, 다소 큰 의미 없는(=질병이 바꿨다기엔 미미한) 챕터도 있어서 아쉽다.

+ Recent posts