Pass std::sync::mpsc::Sender to CoAPServer handle

I'm trying to add a channel to the CoAP server handle:

use coap::{CoAPRequest, CoAPResponse, CoAPServer};

use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};

fn request_handler(request: CoAPRequest, channel_tx : Sender<u8>) -> Option<CoAPResponse> {
    None
}

fn main() {
    let addr = "[::]:5683";
    let mut server = CoAPServer::new(addr).unwrap();   
    let (channel_tx, channel_rx): (Sender<u8>, Receiver<u8>) = mpsc::channel();   
    server.handle( move |request| {
        request_handler(request, channel_tx.clone())
    }).unwrap();
}

This does not work:

error[E0277]: `std::sync::mpsc::Sender<u8>` cannot be shared between threads safely
  --> src/main.rs:14:12
   |
14 |     server.handle( move |request| {
   |            ^^^^^^ `std::sync::mpsc::Sender<u8>` cannot be shared between threads safely
   |
   = help: within `[closure@src/main.rs:14:20: 16:6 channel_tx:std::sync::mpsc::Sender<u8>]`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<u8>`
   = note: required because it appears within the type `[closure@src/main.rs:14:20: 16:6 channel_tx:std::sync::mpsc::Sender<u8>]`
   = note: required because of the requirements on the impl of `coap::server::CoAPHandler` for `[closure@src/main.rs:14:20: 16:6 channel_tx:std::sync::mpsc::Sender<u8>]`

error[E0277]: the trait bound `std::sync::mpsc::Sender<u8>: std::marker::Copy` is not satisfied in `[closure@src/main.rs:14:20: 16:6 channel_tx:std::sync::mpsc::Sender<u8>]`
  --> src/main.rs:14:12
   |
14 |     server.handle( move |request| {
   |            ^^^^^^ within `[closure@src/main.rs:14:20: 16:6 channel_tx:std::sync::mpsc::Sender<u8>]`, the trait `std::marker::Copy` is not implemented for `std::sync::mpsc::Sender<u8>`
   |
   = note: required because it appears within the type `[closure@src/main.rs:14:20: 16:6 channel_tx:std::sync::mpsc::Sender<u8>]`
   = note: required because of the requirements on the impl of `coap::server::CoAPHandler` for `[closure@src/main.rs:14:20: 16:6 channel_tx:std::sync::mpsc::Sender<u8>]`

How to solve this?

The issue is that the top level request handler which accesses channel_tx is called from multiple threads, which Sender does not allow. It's likely that technically there is no issue with it, since the only thing you do with the sender is cloning it before you have an owned version in the thread - but it would still be prevented.

I think you should be able to work around by wrapping the Sender in another Arc. Then only the Arc is shared between threads:

let (channel_tx, channel_rx): (Sender<u8>, Receiver<u8>) = mpsc::channel();
let arc_channel_tx = Arc::new(channel_tx);
    server.handle( move |request| {
        // Extract channel. The first clone() is likely required to get an owned Arc in the current thread.
        let channel_tx: Sender<u8> = arc_channel_tx.clone().deref().clone();
        request_handler(request, channel_tx)
    }).unwrap();

Edit: You might still have the problem with not being able to call Sender.clone() due to !Sync. In that case you might Arc<Mutex<Sender<u8>>>> and lock the mutex before you can take out a copy of the sender. Thinking about it, then you might actually not require the Arc.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.