Pin
- Der Typ
Pin und das Konzept des Pinning sind grundlegende Bausteine des asynchronen Rust-Ökosystems
- Dennoch gehört
Pin zu den Elementen, die schwer zugänglich sind und leicht missverstanden werden
- Dieser Artikel erklärt, was
Pin erreicht, wie es entstanden ist und worin die aktuellen Probleme von Pin bestehen
Requirements
- Um Referenzen in asynchronen Funktionen zu unterstützen, mussten Referenzen innerhalb von
Future gespeichert werden
- Das Problem ist, dass diese Referenzen selbstreferenziell sein können
- Beispielcode:
async fn foo<'a>(z: &'a mut i32) { ... }
async fn bar(x: i32, y: i32) -> i32 {
let mut z = x + y;
foo(&mut z).await;
z
}
- Der interne Zustand von
Bar sieht wie folgt aus:
enum Bar {
Start { x: i32, y: i32 },
FirstAwait { z: i32, foo: Foo<'?> },
Complete,
}
- Das Ziel von
Pin ist es, selbstreferenzielle Typen sicher zu handhaben
Non-solutions: move constructors and offset pointers
- Move-Konstruktoren und Offset-Pointer funktionieren in Rust nicht
- Move-Konstruktoren würden beim Verschieben Pointer anpassen, aber das ist in Rust nicht möglich
- Offset-Pointer funktionieren nicht, weil sich zur Compile-Zeit nicht erkennen lässt, ob eine Referenz selbstreferenziell ist oder nicht
The “pinned typestate”
- Ein Objekt ist nicht immer unbeweglich, sondern muss erst ab einem bestimmten Zeitpunkt unbeweglich werden
- In Ralf Jungs Modell wechselt ein Objekt vom Zustand „owned“ in den Zustand „shared“ und dann in den Zustand „pinned“
- Sobald es in den gepinnten Zustand übergeht, kann das Objekt nicht mehr verschoben werden
?Move
- Vor
Pin wurde eine Lösung auf Basis eines neuen Traits namens Move versucht
- Typen, die
Move nicht implementieren, wechseln beim Nehmen einer Referenz in den gepinnten Zustand
Move bietet jedoch keine Abwärtskompatibilität
Pin
Pin entwirft eine neue Art von Referenz, die ein Objekt in den gepinnten Zustand versetzt
Pin ist als Library-API implementiert und wahrt damit die Abwärtskompatibilität
- Durch das zusätzliche Auto-Trait
Unpin müssen die meisten Typen nicht zwischen gepinntem und normalem Zustand unterscheiden
The problems with Pin
Pin hat verschiedene Probleme bei der Benutzbarkeit
- Da
Pin als Library-Typ implementiert ist, fehlen viele Fähigkeiten gewöhnlicher Referenztypen
- Zum Beispiel implementiert
&mut T nicht Copy, kann aber mehrfach als Argument übergeben werden
Pin bietet diesen Komfort nicht
- Beim Einsatz von
Pin entsteht viel Verwirrung
In my next post…
Pin ermöglicht es, beliebige Referenzen in asynchronen Funktionen sicher zu kompilieren
- Gleichzeitig erhöht
Pin die Komplexität; wie sich das verbessern ließe, wird im nächsten Artikel behandelt
Zusammenfassung von GN⁺
Pin ist ein wichtiger Baustein des asynchronen Rust-Ökosystems
- Die Probleme bei der Benutzbarkeit von
Pin rühren daher, dass es als Library-Typ implementiert ist
- Möglichkeiten zur Verbesserung von
Pin werden im nächsten Artikel behandelt
- Ein Projekt mit ähnlicher Funktionalität ist
pin-project-lite
1 Kommentare
Hacker-News-Kommentare
Pin ist schwer zu verstehen, weil es in der offiziellen Dokumentation nicht klar erklärt wird
Unpin, daher bewirkt Pin normalerweise gar nichtsT, für die Pin tatsächlich funktioniert, ist sehr speziell und wird in der Dokumentation nicht ausreichend hervorgehobenPin ist schwer, weil es für sich genommen keine Bedeutung hat
Pinsagt weder die Sprache noch die Standardbibliothek, was Pin tun kann und was nichtInnerTypezusätzliche (intern unsichere) Methoden und APIs, mit denen sich angeheftete Objekte manipulieren lassenPinselbst besteht darin, einen Zeiger bereitzustellen, der weniger „eingebaute Fähigkeiten“ hatDem Titel sollte „rust“ hinzugefügt werden, damit klar ist, worum es in dem Artikel geht
Der Begriff „value identity“ wird in der Dokumentation von Mojo nirgends definiert
Pin ist ein gutes Beispiel für einen technisch korrekten, aber schwer verständlichen Namen
immovable!(…)besser, aber es ist schwer, einen wirklich guten Namen zu findenprevent_moving!(…)und einPreventMove-Trait könnten besser seinIn Rust-ähnlichen Sprachen mit Move-Konstruktoren könnte die Notwendigkeit für Pin verschwinden
Über
&mut-Referenzen lassen sich Objekte mitmem::swap/replaceverschieben, aber das wird in der Praxis selten benötigtswapundreplaceunsicher zu machen könnte das Problem lösenWithoutBoats führt eine lebhafte Diskussion über asynchrone Iteratoren,
pollundpinPinning/
!Moveist nicht nur für async/await nützlich, sondern auch für viele andere Anwendungsfälle