Ich schreibe einen WebSocket-Server, auf dem ein Web-Client eine Verbindung herstellt, um Schach gegen eine Multithread-Computer-KI zu spielen. Der WebSocket-Server möchte ein Logger
-Objekt an den AI-Code übergeben. Das Logger
-Objekt wird Protokollzeilen von der AI zum Web-Client leiten. Das Logger
muss einen Verweis auf die Clientverbindung enthalten.
Ich bin verwirrt darüber, wie Leben mit Threads interagieren. Ich habe das Problem mit einer Wrapper
Struktur reproduziert, die durch einen Typ parametrisiert ist. Die Funktion run_thread
versucht, den Wert auszupacken und zu protokollieren.
Das Argument wrapper
befindet sich auf dem Stapel und seine Lebensdauer erstreckt sich nicht über den Stapelrahmen von run_thread
hinaus, obwohl der Thread verbunden wird, bevor der Stapelrahmen endet. Ich könnte den Wert vom Stapel kopieren:
Dies funktioniert nicht, wenn T
eine Referenz auf ein großes Objekt ist, das ich nicht kopieren möchte:
Was ergibt:
%Vor% Die einzige Lösung, an die ich denken kann, ist die Verwendung von Arc
.
In meinem realen Programm scheint es, dass sowohl das Logger
als auch das Verbindungsobjekt in Arc
wrappers platziert werden müssen. Es scheint ärgerlich, dass der Client die Verbindung in einer Arc
boxen muss, wenn es intern in der Bibliothek ist, dass der Code parallelisiert ist. Dies ist besonders ärgerlich, da die Lebensdauer der Verbindung garantiert größer ist als die Lebensdauer der Worker-Threads.
Habe ich etwas verpasst?
Die Thread-Unterstützung in der Standardbibliothek ermöglicht es erstellten Threads, den Thread, der sie erstellt hat, zu überleben. das ist gut! Wir sind jedoch nicht auf die Standardbibliothek beschränkt. Mindestens zwei Kisten bieten Scoped-Threads - Threads, die garantiert beendet werden, bevor ein bestimmter Bereich endet. Diese können sicherstellen, dass Stapelvariablen für die gesamte Dauer des Threads verfügbar sind:
Hier sind Beispiele von jedem. Jedes Beispiel erzeugt eine Reihe von Threads und mutiert einen lokalen Vektor an Ort und Stelle ohne Sperren, ohne Arc
und ohne Klonen. Beachten Sie, dass die Mutation einen sleep
-Aufruf hat, um zu überprüfen, ob die Aufrufe parallel stattfinden.
Der Client muss die Verbindung in einem
Arc
einrahmen, wenn es intern in der Bibliothek ist, in der der Code parallelisiert ist
Vielleicht können Sie Ihre Parallelität dann besser verbergen? Können Sie den Logger akzeptieren und ihn dann in ein Arc
/ Mutex
einbinden, bevor Sie ihn an Ihre Threads übergeben?
Tags und Links rust