thread und rvalues
-
Nein, das funktioniert leider nicht. Der Compiler sagt trotzdem dass versucht wurde auf eine gelöschte Funktion zu verweisen (der Kopierkonstruktor). Ich weiß auch nicht wieso genau das nicht funktioniert, MS hat da halt irgendwas sehr komisch implementiert.
-
Kannst Du Dir nicht einen passenden Kopierkonstruktor schreiben?
-
Ich kann bestätigen, dass VS2013 keine Objekte in Threads moven lässt, weder mit std::thread noch mit std::async. Auf der verlinkten Seite ist ein Workaround angegeben:
void myfunc(std::reference_wrapper<myClass>); myClass instance; std::thread(&myfunc, std::ref(instance)).detach();Mir ist aber nicht klar, was das für Auswirkungen hat.
-
Normale Referenz übergeben und dann im Thread moven.
help_fuck_ms schrieb:
MS hat da halt irgendwas sehr komisch implementiert.
Wohl kaum, move-only-Typen in einen Thread zu bekommen ist verdammt kompliziert, habe ich jedenfalls beim Versuch einer std::thread-Implementation nicht hinbekommen. Wenn man darauf nicht achtet kann man das hingegen mit einem simplen std::bind lösen.
-
qqq schrieb:
Normale Referenz übergeben und dann im Thread moven.
Du willst ja sowas machen können:
void foo(std::vector<T> v){ thread(bla, std::move(v)).detach(); }Bei Referenz übergeben und im Thread moven gibt es den vector vielleicht gar nicht mehr. Also muss man warten, bis der Thread mit dem moven fertig ist und muss Threads synchronisieren, was es zu vermeiden gilt. Man kann den vector einem std::auto_ptr anvertrauen oder etwas was anders heißt und dasselbe tut um den Aufschrei zu vermeiden. Man kann auch "sicher gehen" indem man einen std::shared_ptr mitsamt des Overheads in Kauf nimmt. Alles nicht so richtig schön.
-
Also einfach einen shared_ptr auf ein struct thread_arguments oder sowas zu übergeben scheint mir doch die sinnvollste Lösung zu sein diesen VS Bug zu umgehen (der liegt btw nicht unbedingt an der Library, sondern daran dass VS einfach move immer noch nicht vollständig implementiert hat), der Overhead von shared_ptr gegenüber den Kosten einen Thread zu starten ist eh vernachlässigbar.
-
Die schreiben doch selbst dass es an der Library liegt -- weil sie halt std::bind verwenden, was für den Thread-Ctor aber die falsche Semantik hat.
-
nwp3 schrieb:
Du willst ja sowas machen können:
void foo(std::vector<T> v){ thread(bla, std::move(v)).detach(); }Bei Referenz übergeben und im Thread moven gibt es den vector vielleicht gar nicht mehr. Also muss man warten, bis der Thread mit dem moven fertig ist und muss Threads synchronisieren, was es zu vermeiden gilt.
Das Problem gibt es aber nur wenn man es mit
std::refmacht, nen? Der obige Code mitstd::movesollte mMn. ohne Synchroniserung korrekt funktionieren, da das Objektvja erstmal in das Thread-Objekt reingemoved wird, und danach erst der Thread gestartet.
-
hustbaer schrieb:
Der obige Code mit
std::movesollte mMn. ohne Synchroniserung korrekt funktionieren, da das Objektvja erstmal in das Thread-Objekt reingemoved wird, und danach erst der Thread gestartet.Wenn es kompilieren würde sollte es so funktionieren. Tut es aber nicht in VisualStudio. Der Workaround soll aber genauso gut funktionieren. Ich glaube std::ref hat hier keinerlei Vorteil gegenüber einer normalen Referenz und das ist schlecht. Mein Favorit ist immernoch auto_ptr.
-
Jo.
Und... das "in das
threadObjekt reingemoved" von mir ist natürlich Unsinn.Sonst gäbe es ja erst wieder ein Problem wenn das
threadObjekt zu früh zerstört wird.std::threadmuss intern wohl den Funktor den der Thread dann ausführen soll "dynamisch instanzieren", und dann Ownership an die Trampolin-Funktion des Thread transferieren.
Die zu bindenden Parameter müssen in diesen dynamisch instanzierten Funktor reingemoved werden, nicht in dasstd::threadObjekt. Aber halt innerhalb des Konstruktors vonstd::thread.