Модуль watch
sync.Канал с несколькими производителями и несколькими потребителями, который сохраняет только последнее отправленное значение.
Этот канал полезен для отслеживания изменений значения из разных частей кодовой базы, например изменений значений конфигурации.
Использование
channel возвращает пару Sender / Receiver. Это стороны канала — производитель и потребитель. Канал создаётся с начальным значением.
Каждый Receiver независимо отслеживает последнее значение, увиденное вызывающим его кодом.
Чтобы получить текущее значение, хранящееся в канале, и отметить его как увиденное для заданного Receiver, используйте Receiver::borrow_and_update().
Чтобы получить текущее значение, не отмечая его как увиденное, используйте Receiver::borrow(). (Если значение уже отмечено как увиденное, Receiver::borrow() эквивалентен Receiver::borrow_and_update().)
Подробнее о том, когда следует использовать эти методы, см. здесь.
Уведомления об изменениях
Сторона Receiver предоставляет асинхронный метод changed. Этот метод становится готовым, когда через сторону Sender отправляется новое, ещё не просмотренное значение.
-
Receiver::changed()возвращает:-
Ok(())при получении нового значения. -
Err(RecvError), если канал закрыт И текущее значение просмотрено.
-
- Если текущее значение не просмотрено при вызове
changed, тоchangedвернётся немедленно. Если текущее значение просмотрено, метод будет ожидать, пока через сторонуSenderне будет отправлено новое сообщение или покаSenderне будет удалён. - После завершения метод
changedотмечает новое значение как просмотренное. - При создании начальное значение считается просмотренным. Иными словами,
Receiver::changed()не вернётся, пока не будет отправлено следующее значение. - Новые экземпляры
Receiverможно создать с помощьюSender::subscribe(). Текущее значение на момент созданияReceiverсчитается просмотренным.
changed и has_changed
Сторона Receiver предоставляет два метода для проверки изменений в канале: has_changed и changed.
-
has_changed— это синхронный метод, который проверяет, просмотрено ли текущее значение, и возвращает логическое значение. Этот метод не отмечает значение как просмотренное. -
changed— это асинхронный метод, который возвращается, когда в канале появляется непросмотренное значение. Этот метод отмечает значение как просмотренное.
Обратите внимание: есть два различия в поведении этих методов при возврате ошибки.
-
has_changedвозвращает ошибку тогда и только тогда, когда канал закрыт. -
changedвозвращает ошибку, если канал закрыт И текущее значение просмотрено.
В примере ниже показано, как эти методы различаются по условиям возврата ошибки.
borrow_and_update и borrow
Если получатель собирается в цикле ожидать уведомления от changed, предпочтительно использовать Receiver::borrow_and_update(), а не Receiver::borrow(). Это позволяет избежать возможной гонки, при которой новое значение отправляется между моментом готовности changed и чтением значения. (При использовании Receiver::borrow() цикл может выполниться дважды с одним и тем же значением.)
Если получателя интересует только текущее значение и он не собирается ожидать изменений, можно использовать Receiver::borrow(). Использовать borrow может быть удобнее, поскольку это метод &self — для borrow_and_update требуется &mut self.
Примеры
Следующий пример выводит hello! world! .
use tokio::sync::watch;
use tokio::time::{Duration, sleep};
let (tx, mut rx) = watch::channel("hello");
tokio::spawn(async move {
// Use the equivalent of a "do-while" loop so the initial value is
// processed before awaiting the `changed()` future.
loop {
println!("{}! ", *rx.borrow_and_update());
if rx.changed().await.is_err() {
break;
}
}
});
sleep(Duration::from_millis(100)).await;
tx.send("world")?;Различие в условиях возврата ошибки у changed и has_changed.
use tokio::sync::watch;
let (tx, mut rx) = watch::channel("hello");
tx.send("goodbye").unwrap();
drop(tx);
// `has_changed` does not mark the value as seen and errors
// since the channel is closed.
assert!(rx.has_changed().is_err());
// `changed` returns Ok since the value is not already marked as seen
// even if the channel is closed.
assert!(rx.changed().await.is_ok());
// The `changed` call above marks the value as seen.
// The next `changed` call now returns an error as the channel is closed
// AND the current value is seen.
assert!(rx.changed().await.is_err());Закрытие
Sender::is_closed и Sender::closed позволяют производителю определить, когда все дескрипторы Receiver удалены. Это означает, что дальнейший интерес к создаваемым значениям отсутствует и работу можно остановить.
Значение в канале не будет удалено, пока не будут удалены все отправители и все получатели.
Потокобезопасность
И Sender, и Receiver потокобезопасны. Их можно перемещать в другие потоки и использовать в конкурентной среде. Копии дескрипторов Receiver можно перемещать в отдельные потоки и также использовать параллельно.
Модули
- error
- Типы ошибок watch.
Структуры
- Receiver
- Получает значения от связанного
Sender. - Ref
- Возвращает ссылку на внутреннее значение.
- Sender
- Отправляет значения связанному
Receiver.
Функции
- channel
- Создаёт новый канал watch и возвращает дескрипторы для отправки и получения.
MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/sync/watch/index.html