Question on mpsc::channel implementation


#1

Hi Rust experts,

I am trying to understand how mpsc::channels work. https://github.com/rust-lang/rust/blob/master/src/libstd/sync/mpsc/mod.rs

I found that Sender and Receiver is implemented similarly:

pub struct Sender<T> {
    inner: UnsafeCell<Flavor<T>>,
}

And Flavor is:

enum Flavor<T> {
    Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
    Stream(Arc<UnsafeCell<stream::Packet<T>>>),
    Shared(Arc<UnsafeCell<shared::Packet<T>>>),
    Sync(Arc<UnsafeCell<sync::Packet<T>>>),
}

With my limited understanding I see the role of Arc and UnsafeCell. Based on the above I assume that Sender and Receiver encapsulates a type like UnsafeCell<Arc<UnsafeCell<T>>>.

Can someone please explain what the second, outer UnsafeCell is doing here? Why can’t the Sender be like?:

pub struct Sender<T> {
    inner: Flavor<T>,
}

Thank you, David


#2

The channel type is changed dynamically, based on how it is used, so the flavour needs to change. The desire is to have this all happen while shared (i.e. inside &self methods, like clone) and so interior mutability is necessary, which is what UnsafeCell provides.


#3

Thank you, makes sense to me now.