I have an Arc<RwLock<Foo>>
.
Is there a way to make something out of this, on which the RwLock
's write() does not exist? i.e. Is there some form of RLock
which I can make from an RwLock
.
Use case: I have a Foo
. More than one part of my code needs to mutate the Foo (hence the RwLock), but the majority of my code must only ever have read-only access to the Foo.
Is there a way of achieving this? Or is there a way of doing this without RwLock
?
Write your own struct that contains the Arc<RwLock<Foo>>
.
#[derive(Clone, Debug)]
pub struct FooReadOnly(Arc<RwLock<Foo>>);
impl FooReadOnly {
pub fn read(&self) -> LockResult<RwLockReadGuard<'_, Foo>> {
self.0.read()
}
}
(A fully fleshed-out version would also contain a wrapper for try_read()
.)
The general pattern worth noting here is: instead of your data type being visibly inside an Arc<RwLock<...>>
, your public type contains the Arc
. This allows much more flexibility in what kind of “handles” you can offer than exposing the Arc. This is a fairly common pattern in Rust — if you've ever used a library type that notes you can clone it and get another handle to the same thing, there's a good chance it's doing the same thing inside (if it's not actually a handle to an OS resource like a file descriptor).
If you wanted to fully hide the implementation details, you would also wrap the RwLockReadGuard
— all it needs to do is implement Deref<Target = Foo>
and forward that to the guard. Such wrappers can also do things like Deref
ing to some part of the Foo
rather than an &Foo
exactly.