Search code examples
rustrust-tokio

Rust value updatable across tokio threads


I'd like to keep track of a mutable number across multiple threads. I want to pass this incrementable number (u32) to multiple tokio tasks, each of which can increment it and inspect the value in a safe way.

What is the proper data structure for doing so? I suspect it will involve awaiting to update the value.


Solution

  • Fundamentally, based on the comments thread, this question is close to How can I mutably share an i32 between threads? except with the additional constraint of requiring no panic being possible.

    You have 2 major options:

    1. Use architecture-specific atomics with an Arc for sharing across threads like std::sync::atomic::AtomicU32. These are implemented at the hardware level, though you probably still want to consider stuff like unsigned overflow problems as usual. So your type will be Arc<AtomicU32> or so.
    2. Use Arc<Mutex<u64>> which is essentially a more expensive form of (1). Arc is for sharing consistent mutative ownership across threads while Mutex<T> is for making sure "edit-collision" (race condition) doesn't occur for whatever the type T is. If you want to allow for multiple readers at once, use RwLock.

    Note that (2) is vulnerable to panics anyways because the thread that holds the write lock can still panic, leaving the lock in a bad state. There are 2 major implementations for mutex locks in Rust, split between std and parking_lot/tokio:

    • std::sync::Mutex and std::sync::RwLock surfaces this error case every time you try to .lock() as PoisonError<T> (docs).
    • tokio and its underlying parking_lot Mutex implementations decided to not implement poison error detection, so just be aware of this.