Spec-Zone.ru › Tokio

Модуль oneshot

Доступно только при включенной функции crate sync.

Одноразовый канал используется для отправки одного сообщения между асинхронными задачами. Функция channel используется для создания пары дескрипторов Sender и Receiver, образующих канал.

Дескриптор Sender используется отправителем для отправки значения. Дескриптор Receiver используется получателем для получения значения.

Каждый дескриптор можно использовать в отдельной задаче.

Поскольку метод send не является асинхронным, его можно использовать где угодно. В том числе для отправки данных между двумя средами выполнения и из неасинхронного кода.

Если Receiver закрывается до получения уже отправленного сообщения, сообщение останется в канале, пока получатель не будет удален; в этот момент сообщение будет немедленно удалено.

Примеры

use tokio::sync::oneshot;

let (tx, rx) = oneshot::channel();

tokio::spawn(async move {
    if let Err(_) = tx.send(3) {
        println!("the receiver dropped");
    }
});

match rx.await {
    Ok(v) => println!("got = {:?}", v),
    Err(_) => println!("the sender dropped"),
}

Если отправитель будет уничтожен, не отправив сообщение, получение завершится ошибкой error::RecvError:

use tokio::sync::oneshot;

let (tx, rx) = oneshot::channel::<u32>();

tokio::spawn(async move {
    drop(tx);
});

match rx.await {
    Ok(_) => panic!("This doesn't happen"),
    Err(_) => println!("the sender dropped"),
}

Чтобы использовать канал oneshot в цикле tokio::select!, добавьте &mut перед каналом.

use tokio::sync::oneshot;
use tokio::time::{interval, sleep, Duration};

let (send, mut recv) = oneshot::channel();
let mut interval = interval(Duration::from_millis(100));

tokio::spawn(async move {
    sleep(Duration::from_secs(1)).await;
    send.send("shut down").unwrap();
});

loop {
    tokio::select! {
        _ = interval.tick() => println!("Another 100ms"),
        msg = &mut recv => {
            println!("Got message: {}", msg.unwrap());
            break;
        }
    }
}

Чтобы использовать Sender из деструктора, поместите его в Option и вызовите Option::take.

use tokio::sync::oneshot;

struct SendOnDrop {
    sender: Option<oneshot::Sender<&'static str>>,
}
impl Drop for SendOnDrop {
    fn drop(&mut self) {
        if let Some(sender) = self.sender.take() {
            // Using `let _ =` to ignore send errors.
            let _ = sender.send("I got dropped!");
        }
    }
}

let (send, recv) = oneshot::channel();

let send_on_drop = SendOnDrop { sender: Some(send) };
drop(send_on_drop);

assert_eq!(recv.await, Ok("I got dropped!"));

Модули

error
Oneshot типы ошибок.

Структуры

Receiver
Получает значение от связанного Sender.
Sender
Отправляет значение связанному Receiver.

Функции

channel
Создает новый одноразовый канал для отправки отдельных значений между асинхронными задачами.

MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/sync/oneshot/index.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API