Borrowing across threads with Mutex?

I'm writing a Markov Generator bot for a messaging platform called Discord, and I was wondering how I would avoid Borrow Checker errors when doing this:

fn main() {
let token = "kek";
let mut map = Arc::new(Mutex::new(MarkovChain::new()));
let mut client = Arc::new(Mutex::new(Client::login(&token)));

thread::spawn(move || {
    client.lock().unwrap().on_message(move |_ctx, msg| {
        map.lock().unwrap().parse(msg.content.as_str());
        if msg.content == ".markov" {
            let markov = map.lock().unwrap().generate_markov();
            msg.channel_id.say(markov.as_str());
        }
    });
    let _ = client.lock().unwrap().start();
});

}

The error I get when compiling is this:

error[E0373]: closure may outlive the current function, but it borrows map, which is owned by the current function
--> src/main.rs:16:44
|
16 | client.lock().unwrap().on_message( |_ctx, msg| {
| ^^^^^^^^^^^ may outlive borrowed value map
17 | map.lock().unwrap().parse(msg.content.as_str());
| --- map is borrowed here
|
help: to force the closure to take ownership of map (and any other referenced variables), use the move keyword, as shown:
| client.lock().unwrap().on_message( move |_ctx, msg| {

error[E0507]: cannot move out of borrowed content --> src/main.rs:19:30 | 19 | let markov = map.lock().unwrap().generate_markov(); | ^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

error: aborting due to 2 previous errors

1 Like

Are you sure that output is the compilation of the code above? because it says to use move, but it seems like you are using it

You need to clone the Arc and then move the clone into the closure.

2 Likes

Try adding let mut map = map; at the start of first closure.

1 Like