Hi, I'm reading the source of the atomic_refcell crate and I don't understand why AtomicRefCell<T>
requires T
to be Sync
in order to be Send
.
AtomicRefCell
will hand out multiple shared references to the inner value at the same time. If the inner type is not Sync
(i.e. can be mutated in a non-threadsafe manner through a shared reference), then the AtomicRefCell
can't be Send
or multiple threads would be able to have shared references to the value concurrently.
Yes but the AtomicRefCell
is borrowed, it can't be moved to another thread while there is a Ref
in the wild.
It's the same case as RwLock
and it only requires Send
(either std or parking_lot's version).
This looks like an overly conservative bound to me, Send
should only require T: Send
but not T: Sync
. Same as RwLock
Adding a T : Sync
bound on AtomicRefCell<T> : Send
expresses the following:
- If
T : !Sync
(i.e.,T
may not be sound to share / be aliased across multiple threads, such asT = Cell<_>
orT = RefCell<_>
) then it may be unsound to send an unaliasedAtomicRefCell<T>
into another thread.
The only wrappers that need to worry about it are those offering shared (aliased) ownership, such as Rc
and Arc
, since a unique handle on a Arc
does not guarantee that the pointee is not aliased.
But AtomicRefCell<T>
does not offer shared ownership: if you have a unique handle on a AtomicRefCell<T>
, you can obtain a unique handle on the wrappee T
.
Thus the Send
impl should be:
unsafe impl<T : ?Sized> Send
for AtomicRefCell<T>
where
T : Send,
{}
(Regarding the Sync
impl, since &AtomicRefCell<T> -> &T
is possible, it requires at least T : Sync
, and since &AtomicRefCell<T> -> &mut T
is possible, it also requires T : Send
)
Alright, I'm glad I didn't overlook some edge case.
Since I can't choose your two replies as the solution I'll pick @Yandros' for posterity and the hard work put into it. But @RustyYato, yours was enough for me =)
Thank you both.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.