/// A `std::sync::mpsc::Sender` that is also `Sync`. /// /// The builtin `Sender` is not sync, because it uses internal mutability to /// implement an optimization for non-shared one-shot sending. The queue that /// backs the sender initially accepts only one item from a single producer. /// If the sender is cloned, the internal queue turns into a multi-producer /// multi-shot queue. After that, the internal mutability is never invoked /// again for the sender. The `Sender` structure becomes essentially immutable /// and thus, `Sync`. /// /// This optimization, and the internal mutability is meaningless for the /// purpose of this crate. `SharedSender` forces the transition into a shared /// queue, and declares itself `Sync`. /// /// Note that the same reasoning does not apply to the `Receiver`. There are /// more levels of mutability in the `Receiver`. #[derive(Debug)] pub struct SharedSender(std::sync::mpsc::Sender); unsafe impl Sync for SharedSender where T: Sync {} // A better way to implement this might be the following. // // unsafe impl Sync for SharedSender where // std::sync::mpsc::Flavor::Shared: Sync {} impl SharedSender { /// Create a shared sender. pub fn new(inner: std::sync::mpsc::Sender) -> SharedSender { // Force the transition to a shared queue in Sender. let _clone = inner.clone(); SharedSender(inner) } /// A proxy to `std::syc::mpsc::Sender::send()`. pub fn send(&self, t: T) -> Result<(), std::sync::mpsc::SendError> { self.0.send(t) } } impl From> for SharedSender { fn from(inner: std::sync::mpsc::Sender) -> Self { Self::new(inner) } } impl From> for std::sync::mpsc::Sender { fn from(this: SharedSender) -> Self { this.0 } } impl Clone for SharedSender { fn clone(&self) -> Self { Self(self.0.clone()) } }