Closed sporksmith closed 1 year ago
The MutPtr<T>
type is equivalent to an *mut T
, but one that participates in loom
's access tracking, and should be treated as equivalent to a *mut T
. A *mut T
is never Send
(or Sync
), and therefore, a MutPtr<T>
is also !Send
[^1].
Much like a std::cell::UnsafeCell
handing out *mut T
s, a loom::cell::UnsafeCell
that hands out MutPtr<T>
s is primarily intended as a building block for higher-level safe structures and is not aware of the safety invariants of the structures it's used to implement. Therefore, it cannot know under what conditions a pointer to data in that UnsafeCell
can and cannot be safely shared. It's the responsibility of the code that uses an UnsafeCell
to implement Send
and/or Sync
only when a value containing a pointer to that UnsafeCell
can be shared safely. Just like how std::sync::MutexGuard
must manually implement Send
and Sync
, it's correct for determining whether your guard type should be Send
/Sync
to be left up to the user code as well.
I hope that's a useful explanation of why loom
's cell::MutPtr
should not have Send
or Sync
implementations of its own. Let me know if you have any questions!
[^1]: In fact, the reason the MutPtr<T>
type is !Send
is because it contains a *mut T
and doesn't have a manual Send
implementation.
Fair enough; I suppose my thinking for why MutPtr
ought to be Send
if T
is send is roughly equivalent to the argument that the rustnomicon strikes down re making pointers Send
Doing anything useful with a raw pointer requires dereferencing it, which is already unsafe. In that sense, one could argue that it would be "fine" for them to be marked as thread safe. However it's important that they aren't thread-safe to prevent types that contain them from being automatically marked as thread-safe. These types have non-trivial untracked ownership, and it's unlikely that their author was necessarily thinking hard about thread safety.
I'm writing a mutex guard that is
Send
when its inner typeT
isSend
. It holds aMutPtr
internally, which is!Send
.I'm currently working around it by wrapping in a newtype that implements
Send
whenT
isSend
, but it'd be nice to avoid that by havingloom::cell::MutPtr
do this itself.Similarly I suppose
ConstPtr
could implementSend
andSync
whenT
isSync
? (Though that isn't blocking me personally)