it-swarm.com.de

Wie kann eine Funktion auf einem neuen Thread "als ob" ausgeführt werden, ohne dies zu tun?

Gemäß [futures.async]/3 Punkt 1 des C++ - Standards wird, wenn eine Funktion f mit der Startrichtlinie std::async an std::launch::async übergeben wird, f "wie in einem neuen Ausführungsthread" ausgeführt.

Angesichts der Tatsache, dass f alles kann, einschließlich einer Endlosschleife und eines ewigen Blockierens, wie kann eine Implementierung das Verhalten von f bieten, das auf einem eigenen Thread ausgeführt wird, ohne es tatsächlich auf einem eigenen Thread auszuführen? Das heißt, wie kann eine Implementierung den Spielraum nutzen, den der Standard bietet?

19

In den C++ - Referenzen sieht es so aus, als ob hier und hier , es scheint dass das "als ob" -Ziel darin besteht, dem Bibliotheksimplementierer ein gewisses Maß an Freiheit zu lassen. Zum Beispiel heißt es 

als ob sie von std :: thread erzeugt werden (std :: forward (f), std :: forward (args) ...), mit der Ausnahme, dass die Funktion f einen - Wert zurückgibt oder wirft Eine Ausnahme ist, dass es im gemeinsam genutzten Status gespeichert ist, auf den über std :: future zugegriffen werden kann und der async an den Anrufer zurückgibt.

in der ersten Quelle und 

als ob ein Thread-Objekt mit fn und args als Argumenten erstellt wurde, und der Zugriff auf den gemeinsam genutzten Status der zurückgegebenen zukünftigen Datenbank erfolgt

in dieser Sekunde. Es sieht also so aus, als sei das Verhalten ähnlich wie bei std::thread, könnte aber auf andere Weise implementiert werden. Dies ist interessant, da die hier zitierte Phrase Ausführungsthread von std::thread unterscheidbar ist. Dennoch scheint es, dass beide Quellen das as-if auf diese Weise verstehen.

Eine andere Option könnte, wie von François Andrieux vorgeschlagen, die Verwendung von Threadpool zulassen, wie in der ersten Quelle ausgedrückt:

Die Template-Funktion async führt die Funktion f asynchron Aus (möglicherweise in einem separaten Thread, der möglicherweise Teil eines Thread-Pools ist).

6
Mike

Einige Möglichkeiten, auf die ich mir vorstellen kann, dass f in einem neuen Thread "als ob" ausgeführt werden könnte, ohne dass dies tatsächlich der Fall wäre, wenn f tatsächlich keinen mit anderen Threads gemeinsam genutzten Status verwendet. Dann könnte die Implementierung es als separaten Prozess ausführen (da es keinen gemeinsam genutzten Speicherplatz benötigt), es könnte auch einfach als Hauptfunktionsaufruf im Hauptthread ausgeführt werden (wenn dies beweist, dass f nicht blockiert oder beobachtbar ist) Nebenwirkungen, die sich auf diese Weise unterscheiden würden). Es kann auch geplant werden, um auf einem vorhandenen Thread (Thread-Pool) ausgeführt zu werden.

Und wenn Sie dumm sein wollen, könnten Sie auch die Vorstellung berücksichtigen, dass Sie f gar nicht ausführen, da es keine Garantie dafür gibt, wann neue Threads von einem Betriebssystem ausgeführt werden, also eine böse Implementierung Ich könnte nur sagen, dass das Betriebssystem niemals einen Thread mit Ausnahme des Haupt-Threads plant. Daher ist f überhaupt nicht aktiv, wenn es für einen neuen Thread geplant wird. Natürlich ist das dumm/dumm und keine vernünftige Implementierung würde das je tun - aber in Theorie die Sprache erlaubt eine solche degenerierte Implementierung (denke ich).

5
Jesper Juhl

Der Vorteil dieser Lösung ist, wenn Sie die Implementierung für eine bestimmte Rolle in der Multi-Threading-Welt optimiert haben. Da ich an Software-Aktualisierungsprozeduren beteiligt bin, werde ich ein solches Beispiel verwenden. Aus Optimierungsgründen können Sie Folgendes anrufen:

std::thread::hardware_concurrency();

Du wirst erhalten:

Gibt die Anzahl der gleichzeitigen Threads zurück, die von der Implementierung Unterstützt werden.

Angenommen, Sie haben das Ergebnis gleich 4. Sie möchten viele Dinge parallel aktualisieren. Der Haupt-Thread überwacht die Liste der Futures (3 übrig) und prüft von Zeit zu Zeit, ob es erledigt ist oder nicht und wenn Sie fertig sind, führen Sie das nächste aus der ToDo-Liste aus. Profitieren Sie davon, wenn Sie beispielsweise einen anderen Speichertyp wie 1-FileSystem, 2-EEPROM, 3-NOR-Speicher oder ähnliches aktualisieren. Es ist kein Gewinn, wenn Sie die Schleife ohne Verzögerung einchecken, so wie Sie möchten [...] Sie schreiben eine Funktion, die Bitcoins für 50 Millisekunden ausgegraben hat:) und lösen diese zwischen den Prüfungen aus.

Und wie Sie erwähnt haben, haben wir:

vorteil des "als ob" -Winkelraums, den der Standard bietet

5

AFAIK, die C++ - Laufzeitumgebung, kann einige internal (oder spezialisierte) Threads verwalten, die sich von den standard Threads unterscheiden.

Meine Vermutung (ich lerne immer noch die erweiterten Funktionen von C++) ist, dass mit der std::launch::async-Markierung std::async()f in einem neuen internal - Thread gestartet wird.

Sie können f in einem neuen standard Thread starten, indem Sie std::thread verwenden. In diesem Fall werden die Ausnahmen für den aufgerufenen Thread behandelt, und der Hauptcode muss den Rückgabewert von f abrufen.

Mit dem internal - Thread werden der Rückgabewert und die eventuelle Ausnahme in std::future gespeichert, von std::async() zurückgegeben und von den Threads gemeinsam genutzt.

Also "als ob" steht für "als ob ich f mit std::thread starte, aber ich muss nicht". Aber sicher wird f in einem neuen Thread laufen.

Um Ihre Frage nach der Implementierung zu beantworten, wäre es nach dem Ausführen der Laufzeitumgebung standard thread nur der Aufwand, sie für bestimmte Zwecke zu spezialisieren. Siehe auch die Ausführungsrichtlinie für Algorithmen, die Parallelisierung unterstützen .

2
edixon

Ich sehe die Hauptidee von "f wird ausgeführt", als ob in einem neuen Ausführungsthread "" dass f asynchron läuft. Ob es sich um einen neuen Thread oder etwas anderes handelt, sind Implementierungsdetails.

2
wtom

Die einzige Lösung ohne Thread, an die ich denken kann, ist das Time-Slicing von Gestern, das eine Art Multitasking ist. Die Funktionen müssen erneut eingegeben werden. In einem solchen Szenario wird jede Funktion so ausgeführt, als befänden sie sich in unterschiedlichen Threads, obwohl sie sich praktisch in einem einzigen Thread befinden.

1
seccpur

In den Dokumenten heißt es dort:

Die Template-Funktion async führt die Funktion f asynchron aus (möglicherweise in einem separaten Thread, der möglicherweise Teil eines Thread-Pools ist) und gibt eine std :: future zurück, die schließlich das Ergebnis dieses Funktionsaufrufs enthält. 

http://en.cppreference.com/w/cpp/thread/async

0
Truth