Borrowing across threads with Mutex?


#1

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


#2

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


#3

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


#4

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