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.
LockGuard
(even the wrappedResult
) fromread
– FacesavingRwLock
and insteadArc::get_mut()
. – UigurArc<RwLock<Foo>>
, in different threads. – Potsdam