[Solved] How use std::sync::mpsc::channel at iron?


#1
let (tx,rx) = std::sync::mpsc::channel();
router.add_route("restart".to_string(),|_: &mut Request|{
        tx.send(1).unwrap();
        println!("a restart requestt");
        Ok(Response::with((status::Ok, "ok")))
});

===================the error message: ===================
src\main.rs:176:12: 180:7 error: the trait core::marker::Sync is not implemented for the type core::cell::UnsafeCell<std::sync::mpsc::Flavor<i32>> [E0277]
src\main.rs:176 router.add_route(“restart”.to_string(),|_: &mut Request|{
src\main.rs:177 tx.send(1).unwrap();
src\main.rs:178 println!(“a restart requestt”);
src\main.rs:179 Ok(Response::with((status::Ok, “ok”)))
src\main.rs:180 });
src\main.rs:176:12: 180:7 help: run rustc --explain E0277 to see a detailed explanation
src\main.rs:176:12: 180:7 note: core::cell::UnsafeCell<std::sync::mpsc::Flavor<i32>> cannot be shared between threads safely
src\main.rs:176:12: 180:7 note: required because it appears within the type std::sync::mpsc::Sender<i32>
src\main.rs:176:12: 180:7 note: required because it appears within the type [closure@src\main.rs:176:44: 180:6 tx:&std::sync::mpsc::Sender<i32>]
error: aborting due to previous error


#2

Try with

let (tx,rx) = std::sync::mpsc::channel();
router.add_route("restart".to_string(), move |_: &mut Request|{
        tx.send(1).unwrap();
        println!("a restart requestt");
        Ok(Response::with((status::Ok, "ok")))
});

The move keyword will make sure that the environment, including the Sender, is moved into the closure instead of just referenced. Then it shouldn’t require Sync.


#3

thank you!
but, this idea does not solve the problem,the problem persists.


#4

Strange… Is there a new error?

Never mind, I think I might know what’s up. The handler can be shared among multiple threads, so the sender has to be Sync. One way to work around it is to Mutex lock it, but there may be a better solution.


#5

i use Mutex lock solves the problem.
but, have a new problem:

let (tx,rx)= channel();
    let sh = std::sync::Arc::new(std::sync::Mutex::new(tx));
    let rh = std::sync::Arc::new(std::sync::Mutex::new(rx));
    router.add_route("shutdown".to_string(),move|_: &mut Request|{
        &sh.lock().unwrap().send("a shutdown requestt").unwrap();
        Ok(Response::with((status::Ok, "ok")))
    });
    router.add_route("restart".to_string(), move|_: &mut Request|{
        &sh.lock().unwrap().send("a restart request").unwrap();
        Ok(Response::with((status::Ok, "ok")))
    });

===================the error message: ===================
src\main.rs:176:10: 176:12 error: capture of moved value: sh [E0382]
src\main.rs:176 &sh.lock().unwrap().send(“a restart request”).unwrap();
^~
src\main.rs:176:10: 176:12 help: run rustc --explain E0382 to see a detailed explanation
src\main.rs:171:45: 174:6 note: sh moved into closure environment here because it has type alloc::arc::Arc<std::sync::mutex::Mutex<std::sync::mpsc::Sender<&'static str>>>, which is non-copyable
src\main.rs:171 router.add_route(“shutdown”.to_string(),move|_: &mut Request|{
src\main.rs:172 &sh.lock().unwrap().send(“a shutdown requestt”).unwrap();
src\main.rs:173 Ok(Response::with((status::Ok, “ok”)))
src\main.rs:174 });
src\main.rs:171:45: 174:6 help: perhaps you meant to use clone()?
error: aborting due to previous error

use clone() does not work.


#6

You have to clone it outside the closure. Something like this:

let (tx,rx)= channel();
let original_sh = std::sync::Arc::new(std::sync::Mutex::new(tx));
let rh = std::sync::Arc::new(std::sync::Mutex::new(rx));

let sh = original_sh.clone()
router.add_route("shutdown".to_string(),move|_: &mut Request|{
    &sh.lock().unwrap().send("a shutdown requestt").unwrap();
    Ok(Response::with((status::Ok, "ok")))
});

let sh = original_sh.clone()
router.add_route("restart".to_string(), move|_: &mut Request|{
    &sh.lock().unwrap().send("a restart request").unwrap();
    Ok(Response::with((status::Ok, "ok")))
});

You shouldn’t have to lock rh, unless it’s distributed into multiple threads, as well.


#7

Using your suggestions can compile, but one exception are triggered at run.

thread '<unnamed>' panicked at 'calledResult::unwrap()on anErrvalue: "SendError(..)"', ../src/libcore\result.rs:688

it look sh need to unlock?


#8

Looks more like something went wrong with the channel. Did the receiver drop out of scope?


#9

fix the receiver solve the problem.
Thank you so much for your help! :apple: