Как вытащить Pin <& mut T> из Pin > - PullRequest
2 голосов
/ 16 февраля 2020

Я пишу потоковый адаптер, который требует совместного владения потоком.

Правильно ли хранить поток (в частном порядке) в Pin<Arc<Mutex<impl Stream>>>?

Как я могу вызвать poll_next(self: Pin<&mut Stream> в потоке?

1 Ответ

1 голос
/ 16 февраля 2020

Mutex не имеет так называемого структурного закрепления , которое описано в документации к модулю std::pin:

Получается что сам автор структуры данных должен решить, превратится ли закрепленная проекция для определенного поля в Pin<&mut Struct> в Pin<&mut Field> или &mut Field. [...] Как автор структуры данных, вы решаете для каждого поля, будет ли пиннинг «распространяться» на это поле или нет. Пиннинг, который распространяется, также называется "структурным", потому что он следует структуре типа .

Mutex<T> не имеет структурного пиннинга, потому что пиннинг структуры (Mutex) не распространяется на поле (T) - это является безопасным для получения открепленного &mut T от Pin<&mut Mutex<T>> (то есть, используя вместо этого Deref DerefMut и блокировки мьютекса), даже если T и Mutex<T> равны !Unpin.

Чтобы превратить это &mut T в Pin<&mut T>, вы должны сделать еще один уровень непроверенной гарантии, используя unsafe и Pin::new_unchecked, чтобы доказать, что сам T никогда не перемещается. Кажется, это противоречит цели «внешнего» * ​​1039 *.

В зависимости от того, что позволяют ваши структуры данных, вы можете рассмотреть один из следующих вариантов:

  • написание оболочки для Arc<Mutex>, который прикрепляет содержимое Mutex при доступе через Pin (вы не могли реализовать Deref, но вы могли бы написать методы, которые возвращали MutexGuard s и выполняли внутреннее обертывание Pin)
  • просто отправляет разделяемую изменяемость в тип, который реализует Stream, если ваша структура данных позволяет это.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...