跳到主要内容

Module watch

搜索

Module watch 

Source
展开描述

一个多生产者、多消费者的 channel,仅保留最近一次发送的值。

此通道用于从代码库中的多个位置监视值的更改, 例如,配置值的更改。

§Usage

channel 返回一个 Sender / Receiver 对。它们是通道的 生产者和消费者两半。 通道创建时 具有一个初始值。

每个 Receiver 独立跟踪 其调用者最后看到的值。

要访问通道中存储的当前值 并将其标记为已被给定 Receiver 视为已读, 请使用 Receiver::borrow_and_update()

要在将其标记为已读的情况下访问当前值, 请使用 Receiver::borrow()。 (如果该值已标记为已读Receiver::borrow() 等同于 Receiver::borrow_and_update()。)

有关何时使用这些方法的更多信息, 请参阅 此处

§变更通知

Receiver 半提供了 一个异步的 changed 方法。 当通过 Sender 半 发送新的未见过的值时, 此方法就绪。

  • Receiver::changed() returns:
    • Ok(()) on receiving a new value.
    • Err(RecvError) if the channel has been closed AND the current value is seen.
  • If the current value is unseen when calling changed, then changed will return immediately. If the current value is seen, then it will sleep until either a new message is sent via the Sender half, or the Sender is dropped.
  • On completion, the changed method marks the new value as seen.
  • At creation, the initial value is considered seen. In other words, Receiver::changed() will not return until a subsequent value is sent.
  • New Receiver instances can be created with Sender::subscribe(). The current value at the time the Receiver is created is considered seen.

§changed versus has_changed

Receiver 半提供了 两种用于检查通道变化的方法, has_changedchanged

  • has_changed 是一个同步方法, 用于检查当前值是否已读, 并返回一个布尔值。 此方法不会将该值 标记为已读。

  • changed 是一个异步方法, 一旦通道中存在未读过的值, 它就会返回。 此方法确实会将该值标记为已读。

请注意,这两种方法在返回错误时存在两个行为差异。

  • has_changed errors if and only if the channel is closed.
  • changed errors if the channel has been closed AND the current value is seen.

请参见下面的示例,该示例展示了这些方法具有不同的可失败性。

§borrow_and_update versus borrow

如果 receiver 打算在循环中 等待来自 changed 的通知, 则应优先使用 Receiver::borrow_and_update() 而不是 Receiver::borrow()。 这避免了 changed 就绪 与读取值之间 可能发生的竞态。 (如果使用 Receiver::borrow(), 循环可能会使用相同的值运行两次。)

如果 receiver 仅对当前值感兴趣, 而不打算等待更改, 则可以使用 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")?;

关于 changedhas_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());

§关闭(closing)

Sender::is_closedSender::closed 允许生产者检测 何时所有 Receiver 句柄都已被丢弃。 这表明对正在生成的值不再有兴趣, 可以停止工作。

在所有 sender 和 receiver 都被丢弃之前,channel 中的值不会被释放。

§Thread safety

SenderReceiver 都是线程安全的。 它们可以移动到其他线程, 并可在并发环境中使用。 Receiver 句柄的克隆 可以移动到单独的线程, 也可以并发使用。

模块§

error
Watch 错误类型。

结构体§

Receiver
从关联的 Sender 接收值。
Ref
返回内部值的引用。
Sender
向关联的 Receiver 发送值。

函数§

channel
创建一个新的 watch channel,返回"发送"和"接收"句柄。