跳到主要内容

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_changed 和 changed。

  • 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")?;

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

§关闭(closing)

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

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

§Thread safety

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

模块§

error
Watch 错误类型。

结构体§

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

函数§

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