Global sync::mpsc::channel is possible?


#1

Hi all,

is there any , even unsafe, way to get a global couple of (Sender, Receiver) ?

I tried something like this:

static mut RESULT_SENDER: Option<Sender<(r::BlockedClient,
               Result<r::QueryResult,
                      err::RediSQLError>)>> = None;
static mut RESULT_RECEIVER: Option<Receiver<(r::BlockedClient,
                 Result<r::QueryResult,
                        err::RediSQLError>)>> = None;

But when I try to move them out I get an error:

error[E0507]: cannot move out of static item
  │   --> src/lib.rs:472:72
  │    |
  │472 |    r::listen_and_execute(rc, rx, &RESULT_SENDER.unwrap().clone());
  │    |                                   ^^^^^^^^^^^^^ cannot move out of static item

I also tried lazy_static but I ended up opening an issues: https://github.com/rust-lang-nursery/lazy-static.rs/issues/93

Even though I believe that the problem is more complex than a mere syntax one.

Do you have any thoughts?

Simone


#2

To clone the content of the Option without moving it, you can do RESULT_SENDER.as_ref().unwrap().clone().

However, you’ll also find that Sender is not thread-safe (doesn’t implement Sync) and so it can’t be stored in a static. You can wrap it in a Mutex to fix this.

Here’s a minimal working example:

use std::sync::mpsc::*;
use std::sync::*;

fn main() {
    static mut RESULT_SENDER: Option<Mutex<Sender<()>>> = None;
    unsafe {
        let (tx, rx) = channel();
        RESULT_SENDER = Some(Mutex::new(tx));
        let tx = RESULT_SENDER.as_ref().unwrap().lock().unwrap().clone();
    }
}

#3

In this way I am going to acquire the mutex only when I am cloning / pass around the channel, not when I am using it, correct?


#4

Right. Once you clone it, you can use the clone without going through the static Mutex.