upvote
jdcasale you are right that Arc<RwLock<T>> is a code smell but I would take that a bit further that locking immutable data is even more of a smell. The real bad guy in this case is the RwLock not Arc. For anything that you hydrated once and never mutate you do not need the RwLock. Arc just clones the pointer so it is safe to share for concurrent reads so something like Arc<T> is fine and if you need initialization locking then LazyLock<Arc<T>> lets you lock the initialization but then everything else is just a pointer copy.

I hit this recently while building a url unfurl social card renderer for a project which ended up being something like LazyLock<Arc<Database>>

reply
Give me something like boost.multiindex for Rust, and maybe I could think of trying some experiments.

I think C++ is an excellent choice due to its volubility actually. Bc when I want safety, I mostly have it (but I have done a lot of C++, admittedly).

reply
It is interesting to see the different patterns used due to different cases and tastes. For example, my concurrency patterns rarely use locks, and are instead usually one of:

  - Dedicated hardware via DMA, multiple cores/MCUs etc
  - Thread pools (e.g rayon)
  - GPU
  - SIMD
  - Atomics
  - Interrupts and their ISRs
  - Event loops
  - std::sync Thread and MPSC (My Std rust default for not blocking the GUI etc)
reply
Most of it comes down to avoiding shared data. Unfortunately it requires forethought to do that well. There are also many cases where you do want to share data for optimal performance as other options are ultimately too heavyweight.

Also worth noting that an event loop by itself doesn't give you serialization by itself, it can just allow you to gain concurrency without parallelism. You still need some form of serialization by way of something like actors (or async locks).

reply
yeah, locks are expensive.
reply