Shared mutable state in Rust (2022)

draft.ryhl.io

29 points

vinhnx

4 days ago


9 comments

the__alchemist 2 hours ago

I think which tools you use for concurrency depends on your code style and what you're doing. For example, I haven't reached for Arc in a while. Example of the two primary ways I've been doing it:

Embedded: Mutex + critical sections + hardware interrupts. The Mutex isn't std::Mutex, but a hardware-specific one. (E.g. ARM) works in a similar way. The default syntax is a mess of RefCell, Cell, Option, with the requisite < and > characters. (The Option is so you can insert a value in on init, then it's never None) etc. I work around this with macros.

PC applications (GUI, 3D etc): std::thread and MPSC receivers/transmitters which update a state struct when they're ready. Then poll in the GUI's event loop or w/e. I believe this workflow has worked for me in lieu of Arc because I have been structuring programs with a single main thread, then sub threads which perform non-blocking tasks, then return data to the main thread.

Also: If it's a primitive type, Atomics are nice.

FpUser 5 hours ago

I have shared mutable state which is available through the whole application lifetime. Having ARC in this situation makes no sense, single mutex should be all I need.

  • kd5bjo 5 hours ago

    That's also an option available to you: Mutex::new() is const, so there's no trouble putting one in a static variable. If the inner value can't be const-constructed, you'll need a way to prevent access before it's initialized; for that, you can use a OnceLock or just Box::leak() the Mutex once it's constructed and pass around a simple reference.

    • Ciantic an hour ago

      I happen to be just now experimenting with app states. Out of interest, you mean something like this? https://gist.github.com/Ciantic/63526ebfe65570b669eca33bf340...

      What would be disadvanatages of this approach? I don't like Arc's myself either, I would like to see what is best alternative for those in multi threaded apps.

      • maxbond 11 minutes ago

        Different commenter but yes, that's exactly what they mean.

        The main disadvantage is strong coupling. The shared state inside the static makes it more difficult to test your code. There are ways to reduce this coupling, the most obvious being that you push as much logic as possible into functions that accept a reference rather than use your static directly. Then you minimize the size of the code which is difficult to test, and cover it with end to end testing.

        The OnceLock does impose 1 atomic operation of overhead, whereas an Arc imposes 2 (in this case, it can be more if weak references are used). However neither are likely to be important when you consider the overhead of the Mutex; the Mutex is likely to involve system calls and so will dominate the overhead. (If there's little to no contention then the Mutex is a lot like an Arc.)

        Your alternative would be to use `Box::leak()` as the parent comment describes, which would force you to pass a reference around (resulting in better coupling) and eliminate overhead from OnceLock. However, it's probably not worth pursuing for performance benefits alone.

  • mplanchard 3 hours ago

    You can Box::leak() it to make a &’static ref to it.

  • LtdJorge 5 hours ago

    Use a LazyLock for your state, then