Allow unguarded access to an RwLock's inner value using unsafe · Issue #531 · rust-lang/libs-team (original) (raw)
Proposal
Problem statement
I would like to be able to avoid pointer casts for unguarded accesses of the inner value of an RwLock
, similar to RefCell
s try_borrow_unguarded.
Motivating examples or use cases
I am the maintainer of the readlock crate.
About this crate
At its core, this crate provides a a few types that can act as a replacement for Arc<RwLock<T>>
if only a single clone of that Arc
is ever used for writing. This is done by introducing two wrapper types around Arc<RwLock<T>>
, Shared<T>
which can be used for writing but cannot be cloned, and ReadLock<T>
which can be obtained from Shared<T>
and cloned, but only used for reading. Splitting the capabilities into two types like this reduces the potential for deadlock bugs for code that fits this pattern, and can allow downstream crates to expose a handle to some internally-managed state in a read-only way without introducing custom lock types.
Its type Shared<T>
has shared ownership of an RwLock<T>
, but guarantees that no other reference to that RwLock
ever locks it for writing. It also requires &mut self
for write-locking the inner value. Due to this, it can implement Deref<Target = T>
.
To implement Deref<Target = T>
, I currently call .read()
on the inner RwLock
, then (unless there's a PoisonError
) dereference the RwLockReadGuard
and unsafely lifetime-extend the resulting reference using two casts (to raw pointer and back).
If I could instead call an unsafe fn
on the RwLock
with clear safety requirements that gives me &T
directly w/o going through RwLockReadGuard
, it would be a lot easier for me to prove my code sound - I am pretty certain the concept is sound (but happy to be proven wrong), but less certain about the current implementation being sound.
Further, and this may deserve to be split into its own ACP, but it seems worth pointing out here: It should also be sound here, and benefit performance, if the new API also allowed un_checked_ access to the inner value, i.e. if it did not require any reads the reader / writer count of the RwLock
.
Solution sketch
Honestly, I don't know. I guess a direct equivalent of RefCell::try_borrow_unguarded
would be possible and solve my bigger problem around soundness, but it would be really nice to get the performance benefits of unchecked access as well.
Alternatives
As described above, I already have an implementation of the sort of thing this would enable, I'm just not sure whether it's sound. See the readlock
crate's source if you want to see the details.