Canais Assíncronos

Vários crates têm suporte para canais assíncronos. Por exemplo, tokio:

use tokio::sync::mpsc::{self, Receiver};

async fn ping_handler(mut input: Receiver<()>) {
    let mut count: usize = 0;

    while let Some(_) = input.recv().await {
        count += 1;
        println!("Recebido {count} pings até agora.");
    }

    println!("_ping_handler_ completo");
}

#[tokio::main]
async fn main() {
    let (sender, receiver) = mpsc::channel(32);
    let ping_handler_task = tokio::spawn(ping_handler(receiver));
    for i in 0..10 {
        sender.send(()).await.expect("Falha ao enviar _ping_");
        println!("Enviado {} pings até agora.", i + 1);
    }

    drop(sender);
    ping_handler_task.await.expect("Algo deu errado na tarefa do gerenciador de _ping_");
}
This slide should take about 8 minutes.
  • Altere o tamanho do canal para 3 e veja como isso afeta a execução.

  • No geral, a interface é semelhante aos canais sync vistos na aula da manhã.

  • Tente remover a chamada std::mem::drop. O que acontece? Por quê?

  • O crate Flume tem canais que implementam tanto sync quanto async send e recv. Isso pode ser conveniente para aplicações complexas com tarefas de processamento de I/O e CPU pesadas.

  • O que torna o trabalho com canais async preferível é a capacidade de combiná-los com outras futures para combiná-los e criar um fluxo de controle complexo.