I'm writing a stream adapter that requires a shared ownership of the stream.
Is it correct to store the stream (privately) in Pin<Arc<Mutex<impl Stream>>>
?
How can I call poll_next(self: Pin<&mut Stream>
on the stream?
Mutex
does not have what is called structural pinning, which is described in the std::pin
module documentation:
It turns out that it is actually up to the author of the data structure to decide whether the pinned projection for a particular field turns
Pin<&mut Struct>
intoPin<&mut Field>
or&mut Field
. [...] As the author of a data structure you get to decide for each field whether pinning "propagates" to this field or not. Pinning that propagates is also called "structural", because it follows the structure of the type.
Mutex<T>
does not have structural pinning because the pinned-ness of the struct (the Mutex
) does not propagate to the field (the T
) -- it is safe to get an unpinned &mut T
from a Pin<&mut Mutex<T>>
(i.e., by using Deref
instead of DerefMut
and locking the mutex), even if T
and Mutex<T>
are !Unpin
.
In order to turn this &mut T
into a Pin<&mut T>
, you have to make another layer of unchecked guarantee, using unsafe
and Pin::new_unchecked
, to prove that the T
itself is never moved. This seems to defeat the purpose of the "outer" Pin
.
Depending on what your data structures allow, you might consider one of these options:
Arc<Mutex>
that pins the contents of the Mutex
when accessed through a Pin
(you couldn't implement Deref
, but you could write methods that returned MutexGuard
s and did the Pin
-wrapping internally)Stream
, if your data structure allows it.