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.
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.
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.
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.
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.
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.
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.
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.
You can Box::leak() it to make a &’static ref to it.
Use a LazyLock for your state, then