Aufrufen einer Methode als eigener Thread
-
Leider ist Multithreading in C++ nur extrem low-level möglich. thread und scoped_thread sind ein klares Zeichen dafür.
Alles was du eigentlich machen willst, sind einige von einander unabhängige Tasks ausführen. Jeder bessere Sprache bietet da Tasks und Task-Scheduling oder so an. Damit wird der Code abstrakter (du willst Tasks ausführen, nicht Thread-Management betreiben), man macht weniger Fehler und der Code wird performanter (da es Threadpools und so ermöglichst).
In C++ geht das nicht. Entweder ist es nicht vorhanden, oder völlig kaputt (std::async).
Deshalb kann ich zum Multithreading leider C++ nicht empfehlen. Wenn du bei einer Systemsprache bleiben willst, empfehle ich Rust.
-
Joa. Keine Ahnung hoam wie weit das Projekt des TE schon ist und wofür er das macht, aber gleich mal vorschlagen, 'ne andere (und noch dazu eine noch experimentelle) Programmiersprache zu benutzen, wa? Diese Rust-Manie geht mir langsam richtig aufn Keks.
-
müssen schrieb:
man macht weniger Fehler und der Code wird performanter (da es Threadpools und so ermöglichst).
In C++ geht das nicht. Entweder ist es nicht vorhanden, oder völlig kaputt (std::async).
Deshalb kann ich zum Multithreading leider C++ nicht empfehlen. Wenn du bei einer Systemsprache bleiben willst, empfehle ich Rust.
Naja um mal eine Lanze für C++ zu brechen, Threadpools können auch in C++ implementiert werden und es gibt Tonnen von multigethreadetem C++ Code in der Welt.
Ich stimme allerdings zu das Multithreading in C++ sehr komplex ist und man muss sehr darauf achten was man tut, um sicheren Code zu produzieren.Was Rust angeht: "Where is no such a thing as a free lunch." , deswegen gibt es C++ auch seit über 35 Jahren.
P.S.: Meine persönliche Abneigung gegen jede neue "Killersprache" die wöchentlich auf den Markt geworfen wird mag meine Haltung möglicherweise verfestigen.
P.P.S: Bei Rust immer schön auf die * achten.
"* In theory. Rust is a work-in-progress and may do anything it likes up to and including eating your laundry. "
-
Die Moderation kann hier ruhig häufiger mal Posts verschieben.
Z.B. finde ich müssens Beitrag und die Antworten wären gut in RudP aufgehoben.Hier ist's nämlich offtopic und wenn's gelöscht wird mault er rum.
Der vielsagende Titel "Ich empfehle Rust" würde seinen Beitrag angemessen zusammenfassen und sein Anliegen zum Ausdruck bringen.
-
Du brauchst bei std::thread kein std::bind, der Ctor macht das bereits selbst.
-
Kellerautomat schrieb:
Du brauchst bei std::thread kein std::bind, der Ctor macht das bereits selbst.
Ja, aber nur, wenn du
std::ref
benützt. Das wäre dann eine der vielen anderen Möglichkeiten.Edit: Stimmt, man kann's natürlich auch als Pointer übergeben, bin noch etwas von den Workarounds um einen alten VS-Bug geschädigt.
-
Jodocus schrieb:
Kellerautomat schrieb:
Du brauchst bei std::thread kein std::bind, der Ctor macht das bereits selbst.
Ja, aber nur, wenn du
std::ref
benützt. Das wäre dann eine der vielen anderen Möglichkeiten.Geht auch ohne ref. Das std::bind von dir hat gar keine Wirkung.
Jodocus schrieb:
Joa. Keine Ahnung hoam wie weit das Projekt des TE schon ist und wofür er das macht, aber gleich mal vorschlagen, 'ne andere (und noch dazu eine noch experimentelle) Programmiersprache zu benutzen, wa?
Es ging ums Lernen von Multithreading, da ist es doch wohl egal, welche Programmiersprache er nutzt.
Die Sache mit C++ ist halt:
std::thread/std::async/... sind (in der jetztigen Form) unbrauchbar.
TBB und ein paar andere Bibliotheken sind brauchbar, aber kompliziert.Andererseits ist Multithreading in einigen anderen Sprachen (ich lege mich diesmal nicht genauer fest) sicherer und besser unterstützt mit Taskpools und Channels anstatt Threads und Mutexen.
-
müssen schrieb:
Die Sache mit C++ ist halt:
std::thread/std::async/... sind (in der jetztigen Form) unbrauchbar.Sorry, aber so eine Behauptung ist ohne Begründung schlicht nicht zulässig.
Warum ist deiner Meinung nach Std::thread und Std::asynchron unbrauchbar?
-
Ruvi schrieb:
müssen schrieb:
Die Sache mit C++ ist halt:
std::thread/std::async/... sind (in der jetztigen Form) unbrauchbar.Sorry, aber so eine Behauptung ist ohne Begründung schlicht nicht zulässig.
Warum ist deiner Meinung nach Std::thread und Std::asynchron unbrauchbar?Plain Threads are the GOTO of todays computing
Bspw., hab jetzt nicht genau im Kopf, ob das genau dadrauf eingeht.
-
Ruvi schrieb:
müssen schrieb:
Ab C++11 muss man das nicht mehr.
Ja, stimmt Du hast recht. Ich habe mich unglücklich ausgedrückt.
patrick246 schrieb:
Wir legen eben für jedes Element im Array einen Thread an. Anschließend warten wir darauf, bis diese fertig sind.
std::vector<std::thread> threads; for(auto& o : obj) { threads.emplace_back(std::bind(&test::call, &o)); } for(auto& t : threads) { t.join(); }
(ungetestet)
.
Hey leute kann mir jemand vlt. die Syntax erklären wieso benutzt man '&' Operator und ':' und '::' irgendwie ist mir das ganze so richtig nicht geläufig unter C++. Bei Klasse nehme ich '::' bei der Deklaration und bei namespaces nehme ich auch '::' aber in diesem Fall
Danke Gruß
-
Also soweit ich das jetzt verstehe ist das sowas:
for(std::vector<test>::iterator it = objs.begin(); it != objs.end() ; it++)
OK das müsste die for Anweisung sein.
-
for(auto x : container){}
Ist das sogenannte Range-Based-For, oder in anderen auch Sprachen auch als foreach bekannt (z.B. C#, in Java wird es fast genau wie in C++ geschrieben). Das iteriert über deinen gesamten Container (genauer gesagt, über den gesamten Bereich, den die rechte Seite aufgrund von Iteratoren[begin/end] darbietet). Das 'x' ist jeweils das aktuelle Objekt im Container und kann nach belieben ein Value, eine Referenz oder auch das gleich in const sein. Nachteil ist, dass du keinen Index oder den unterliegenden Iterator mehr zur Verfügung hast, was man manchmal (selten) braucht.
Die :: bennen die Methode einer Klasse:
#include <iostream> class Foo { public: void meth(){ std::cout << "Meth" << std::endl; } static void smeth(){ std::cout << "SMeth" << std::endl; } }; int main() { Foo f; f.meth(); (f.*(&Foo::meth))(); Foo::smeth(); }
Das solltest du kennen. Wenn du jetzt Funktionszeiger dazu nimmst, dann reicht nicht den Methodennamen (also meth) zu schreiben, sondern du musst dazuschreiben, dass es um die Methode der Klasse Foo geht -> Fooo::meth. Und da wir die Adresse haben wollen brauchen wir das & davor -> &Foo::meth.
Um die Methode allerdings aufzurufen brauchen wir noch ein Object...Und du siehst, das sieht gar nicht mal so schön aus...
-
Skym0sh0 schrieb:
for(auto x : container){}
Wichtig zu wissen ist auch, dass das insert/delete von Elementen innerhalb einer ranged-based for undefined behavior verursacht.
-
Danke soweit alles verstanden bis auf:
for(auto& t : threads)
Wieso muss es eine Referenz sein?
-
Muss es nicht. Sonst wird eben jeder einzelne Wert in diese Variable kopiert. Wenn du das nicht willst (bzw. kannst, denn manche Objekte kann man nicht kopieren), z.B. weil du die Werte verändern möchtest, nimmst du Referenzen.
-
Naja ohne kriege ich ein Fehler das er auf eine gelöschte FKT zugreift.
Und diese Zeile:
threads.emplace_back(std::bind(&test::call, &o));
ist doch für mich nicht richtig verständlich. Wieso fügen wir am ende vom container von threads binds ?! ein ?!
-
Grnom123 schrieb:
Wieso fügen wir am ende vom container von threads binds ?! ein ?!
Das bind kannst du weglassen.
Und die Frage sollte sich klären, wenn du emplace_back nachschaust.
-
bindungsenergie schrieb:
Grnom123 schrieb:
Wieso fügen wir am ende vom container von threads binds ?! ein ?!
Das bind kannst du weglassen.
Und die Frage sollte sich klären, wenn du emplace_back nachschaust.Habe ich schon davor nachgeschaut? Ich füge ein Element am Ende des Containers ein?
-
Grnom123 schrieb:
bindungsenergie schrieb:
Grnom123 schrieb:
Wieso fügen wir am ende vom container von threads binds ?! ein ?!
Das bind kannst du weglassen.
Und die Frage sollte sich klären, wenn du emplace_back nachschaust.Habe ich schon davor nachgeschaut? Ich füge ein Element am Ende des Containers ein?
Jain, du konstruierst mit emplace_back IM vector ein Objekt.
pushback erstellt erst das Objekt und kopiert/moved es dann in den Vector rein.
Pushback bietet Dir also eine strong exception gurantee während emplace_back das Objekt direkt im Vector erstellt.Vielleicht ist diese Schreibweise unter Umständen anschaulicher:
threads.emplace_back(thread(std::bind(&test::call, &o)));
Du fügst also keinen bind in den Vector ein sondern du erstellst im Vector einen thread mit dem bind als thread constructor parameter.
-
Ruvi schrieb:
Ja, wobei mir der Zusatz noch besser gefällt:
Inserts a new element at the end of the vector, right after its current last element.Der entscheidende Zusatz kommt kurz danach:
This new element is constructed in place using args as the arguments for its constructor.
D.h. es wird sowas wie
push_back(std::thread(args))
, hierpush_back(std::thread(std::bind(&test::call, &o)))
aufgerufen.Da sieht man dann auch, dass std::bind unnötig ist:
push_back(std::thread(&test::call, &o))
oder
emplace_back(&test::call, &o)
tuts deshalb auch.