`tokio::sync::broadcast::Receiver<T>` 不支持克隆操作。

huangapple go评论113阅读模式
英文:

tokio::sync::broadcast::Receiver<T> is not Clone

问题

我有一个像这样的结构体:

#[derive(Clone)]
struct Foo {
    ...  // 其他状态
    receiver: tokio::sync::watch::Receiver<T>,
}

但是我意识到,为了应用程序的目的,我实际上需要一个tokio::sync::broadcast通道,它本身只在Sender半部分实现了Clone,而不是Receiver。所以我不能简单地将Receiver替换为Clone,因为无法派生Clone。也许手动实现Clone是答案,但我不确定它会是什么样子。我认为它需要一个对发送方的处理和一个对sender.subscriber()的调用。我不确定这是否是正确的方法。

如果通道类型更改为广播,我如何拥有一个类型为Foo的类型,我可以克隆句柄,其中每个句柄都能等待接收新消息?

英文:

I have a struct like this:

#[derive(Clone)]
struct Foo {
    ...  // other state
    receiver: tokio::sync::watch::Receiver&lt;T&gt;,
}

But I realize for purposes of the application I actually need a tokio::sync::broadcast channel, which itself only implements Clone in the Sender half, not the Receiver. So I can't simply make a drop-in replacement for the receiver as Clone can't be derived. Maybe a manual Clone implementation is the answer, but I'm not sure what that would look like. It requires a handle to the sender and a call to sender.subscriber() I believe. Not sure this is the right approach.

How can I have a type Foo which I can clone handles to where each one is capable of awaiting to receive a new message, if the channel type changes to broadcast?

答案1

得分: 2

tokio::sync::broadcast中,通过调用Sender上的subscribe方法来创建接收者,就像模块文档所述:

> 调用Sender::subscribe可以创建新的Receiver句柄。返回的Receiver将接收在调用subscribe之后发送的值。

但是,您还可以通过在其上调用resubscribe来创建新的Receiver。这将:

> 从当前尾部元素重新订阅通道。
>
> 此接收者句柄将接收到在重新订阅之后发送的所有值的克隆。这不包括在当前接收者的队列中的元素。

当然,此方法仅适用于T: Clone

因此,如果要使您的Foo可克隆(并且愿意接受Receiver文档中提到的限制),您必须手动实现它:

struct Foo<T> {
    ...  // 其他状态
    receiver: tokio::sync::watch::Receiver<T>,
}

impl<T: Clone> Clone for Foo<T> {
    fn clone(&self) -> Self {
        Self {
            ... // 克隆其他状态
            receiver: self.receiver.resubscribe(),
        }
    }
}
英文:

Receivers in tokio::sync::broadcast are created by calling subscribe method on Sender as the module documentation says:

> New Receiver handles are created by calling Sender::subscribe. The returned Receiver will receive values sent after the call to subscribe.

However you can also create new Receiver by calling resubscribe on it. Which will:

> Re-subscribes to the channel starting from the current tail element.
>
> This Receiver handle will receive a clone of all values sent after it has resubscribed. This will not include elements that are in the queue of the current receiver.

And this method is of course only available for T: Clone.

So if you want your Foo to be Clone (and you are willing to accept limitations mentioned in the Receiver documentation), you have to implement it manually:

struct Foo&lt;T&gt; {
    ...  // other state
    receiver: tokio::sync::watch::Receiver&lt;T&gt;,
}

impl&lt;T: Clone&gt; Clone for Foo {
    fn clone(&amp;self) -&gt; Self {
        Self {
            ... // clone other state
            receiver: self.receiver.resubscribe(),
        }
    }
}

huangapple
  • 本文由 发表于 2023年8月10日 18:56:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76875064.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定