`UnsafeCell` and slices, and decrete `RwLock`s
โ Rust ๐ 2026-07-15 ๐ค surdeus ๐๏ธ 2Background
I am trying to implement a flat list which contains sublists of the same size where each sublist is guarded by its own RwLock.
So, something like this:
use std::cell::UnsafeCell;
use crossbeam::utils::CachePadded;
use parking_lot::RwLock;
struct Layers {
data: Box<[UnsafeCell<u32>]>, // I may have say N "virtual array" of size 16.
rwlocks: Box<[CachePadded<RwLock<()>>]>, // Then, I will have an RwLock for each "virtual array", so a total of N here.
}
First Question
Which type should be used for data?
Box<UnsafeCell<[u32]>>: It's quite unintuitive to create a value of this type, one has to go throughVec::into_boxed_slice,Box::into_raw, pointer casting,Box::from_raw, etc. But I think this has the "most correct" provenance for the pointers obtained fromUnsafeCellin the sense that they have write permission over the whole region of the slice.Box<[UnsafeCell<u32>]>: For my use case, I will need to mutate other elements through a pointer to some element. In my understanding, the pointer may have the correct spatial permission as it inherited that from the slice but may not have the correct mutation permission (due to the requirement to useUnsafeCell::getandUnsafeCell::raw_get). In Does UnsafeCell::raw_get preserve pointer provenance? ยท Issue #474 ยท rust-lang/unsafe-code-guidelines ยท GitHub, RalfJung mentioned that:- ... However we reserve the right to have something more strict in the future where if you do not go through
raw_get, you are not allowed to perform mutation of the cell's contents ... UnsafeCell::raw_getdoes not do any "narrowing" of provenance to the type -- the entire memory range of the original provenance is preserved ...
- ... However we reserve the right to have something more strict in the future where if you do not go through
UnsafeCell<Box<[u32]>: This feels even more wrong, to me theUnsafeCellis not enabling interior mutability to the memory region but theBoxitself instead.
Second Question
Is it sound/safe/etc. to use separated RwLocks that doesn't wrap the values (i.e., RwLock<()>)?
For one, although I believe RwLock does provide the required semantics for MT-safe access, UnsafeCell only mentioned atomics for synchronizing conflicting access: ... conflicting non-synchronized accesses must be done via the APIs in core::sync::atomic..
I'm not even sure if my reasoning is correct. Please correct me if there is any inaccurate description of the semantics. Help appreciated!
FYR: Read/Write guard for sublists (click for more details)1 post - 1 participant
๐ท๏ธ Rust_feed