Search code examples
rustrwlock

How does `write` mode on a `RwLock` work if it isn't mutable?


So, I was writing some code and apparently R.A. didn't warn me about some erroneous stuff I had written in regards to how ownership works with lambdas.
So, a friend helped me rewrite some of my code, and this is just a play example, but their new code boils down to this:

let vec = Rc::new(RwLock::new( Vec::new() ));
let vec_rc = vec.clone();
let my_lambda = || -> () {
  vec_rc.write().unwrap().push(/* ... */);
}

But what I don't understand is how this works if vec_rc isn't mut.
From my prior knowledge, mutable in Rust cascades; in other words, if the "master-containing" object is immutable the rest will have to be too.

Could I please get some clarity as to what goes on under the hood?
Or is their code erroneous too?


Solution

  • From my prior knowledge, mutable in Rust cascades; in other words, if the "master-containing" object is immutable the rest will have to be too.

    This is almost always true... Until we consider interior mutability.

    Interior mutability is exactly about that: changing a value through a shared reference. Moreover, while there are other shared references to it. The basic interior mutability primitive is UnsafeCell, but there are multiple abstractions built on top of it - one of them is RwLock (you can see it secretly contains an UnsafeCell).

    As a side note, Rc<RwLock<T>> is almost always wrong: Rc is non thread safe, which defeats the whole purpose of RwLock. If you just need shared mutable stated over one thread, use Rc<RefCell<T>>. It is much more performant and can't block (so no deadlock debugging, just a simple panic if something went wrong).