Search code examples
multithreadingasynchronousrustthread-safety

Mutating parent state asynchronously inside of child thread


I have an application that primarily acts as a web server and I am trying to implement a background task that mutates variables from the main thread every second.

The following code snippet has a similar structure to my actual code, this code is inside the main function:

let mut counter: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));

thread::spawn(move || async {
    let mut interval = time::interval(time::Duration::from_secs(1));
    let mut counter_clone = counter.lock().await;
    loop {
        interval.tick().await;
        *counter_clone += 1;
    }
});

The compiler has the following message which does make sense, but what I am trying to do seems like a common problem and I'm hoping someone can offer some guidance.

Compiler error:

async block may outlive the current function, but it borrows `counter`, which is owned by the current function

may outlive borrowed value `counter`

My thinking is that if the main thread dies, the child thread will die anyway.

Any help will be appreciated.


Solution

  • Compiler help you:

    help: to force the async block to take ownership of `counter` (and any other referenced variables), use the `move` keyword
       |
    10 |     thread::spawn(move || async move {
    11 |         let mut interval = time::interval(time::Duration::from_secs(1));
    12 |         let mut counter_clone = counter.lock().await;
    13 |         loop {
    14 |             interval.tick().await;
    15 |             *counter_clone += 1;
     ...
    

    You need to move it in the async context:

        thread::spawn(|| async move {
            let mut interval = time::interval(time::Duration::from_secs(1));
            let mut counter_clone = counter.lock().await;
            loop {
                interval.tick().await;
                *counter_clone += 1;
            }
        });
    

    Playground