Reputation: 4941
I have a struct like this:
#[derive(Clone)]
struct Foo {
... // other state
receiver: tokio::sync::watch::Receiver<T>,
}
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?
Upvotes: 3
Views: 1567
Reputation: 6120
Receivers in tokio::sync::broadcast
are created by calling subscribe method on Sender
as the module documentation says:
New
Receiver
handles are created by callingSender::subscribe
. The returnedReceiver
will receive values sent after the call tosubscribe
.
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<T> {
... // other state
receiver: tokio::sync::watch::Receiver<T>,
}
impl<T: Clone> Clone for Foo {
fn clone(&self) -> Self {
Self {
... // clone other state
receiver: self.receiver.resubscribe(),
}
}
}
Upvotes: 5