Compare clones of `Sender<T>`s

Hi everyone, I'm looking for a way to compare clones of mpsc::Sender<T>s with each other.

I'm using channels to implement something of a subscription model where clients send a clone of their Sender<T> down a separate channel, When a message needs to be sent, each client's Sender<T> can be invoked individually, repeatedly.

My issue now is though, that when clients which to unsubscribe, they send the request, along with a copy of their Sender<T>, which I now need to look up in my list of Sender<T>s and remove it.

My current solution (which doesn't work, hence my question) is to use std::ptr::eq().

fn unsubscribe(&mut self, sender: mpsc::Sender<Command>) {
    if let Some(index) = self.subscribers
      .iter()
      .position(|subscriber| std::ptr::eq(subscriber, &sender)) {
        self.subscribers.remove(index);
    }
}

After much hair-out-pulling I realised that this can't work because by nature, Sender<T> are passed by value - they get copied!!!

So I did some googling, and Rust apparently has no standard ways to binary compare values, unless the value implements Eq or PartialEq.

So what might be my best approach here?

Thanks

Crossbeam has same_channel method.

In std this method is not exposed, so you will need to assume senders are not comparable. If you wrap them in Arc<Sender<Command>> then you will be able to use Arc::ptr_eq. Alternatively wrap the Sender in a struct that contains a unique ID alongside it.

3 Likes

Maybe worth noting that this of course only works if there exist no clones of the Sender but only clones of the Arc. Otherwise you'd get false negatives.

Hm, that's another source of issues, as I have no guarantee over this, since I'm writing a library which receives these Sender<T>s...

Thank you, I'll refactor to use crossbeam

Of course the same problem exists for the solution with the wrapper containing a unique ID. The only difference is that with Arc::ptr_eq the problem may be less obvious.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.