A while ago I wrote Diplomatic Bag as a way to deal with
!Send types while inside a multithreaded Tokio runtime, where it's really helpful if everything is
Send. It does this by spawning a globally shared worker thread and all operations on the types are performed on that thread, the user is just given a handle. While writing that I hit an existential question of what I was actually allowed to do with
!Send types, and equivalently
Sync types (I'm happy with
T: Sync <=> &T: Send).
From the 'nomicon:
A type is Send if it is safe to send it to another thread.
Following the letter of that statement, the worker thread can have a map of handles to values and allow those handles to send closures over channels to act on those objects. However, all the values must have the
'static lifetime as their lifetime can't be lexically related to the handles.
Following more of the spirit of that statement, the handle could be the bytes of the type hidden behind
ManuallyDrop. Now lifetimes work as expected, but the value may be living in another thread's stack frame. The worker thread will see references to it, that will look no different than if it was on the heap. You also have to occasionally pass the bytes over a channel to and from the worker thread but that will just look like the value has moved (
Pin could be interesting but I don't think it matters).
Breaking things further, as long as the operation on a different thread doesn't know anything about the type then nothing it could do could break the
!Send-ness of the type? This is most easily demonstrated in this bit of code which turns a
Handle<Result<T, E>> into a
Result<Handle<T>, Handle<E>>, all on whatever thread the
Handle happens to be on. I think this is safe because
Result doesn't introduce any
!Send-ness but this is stretching things.
At the extreme, a
!Send type could have some methods on it that are safe to call from another thread because they don't touch whatever part of the value makes it
!Send. That makes me wonder if send-ability of values is even the right way to model this.
So, what is
unsafe code allowed to do with
Some previous discussion happened on Reddit here.