warum brauchen wir sowohl std :: promise als auch std :: future?

8

Ich frage mich, warum wir beide std :: promise und std :: future brauchen? Warum c ++ 11 Standard Get und Set_value in zwei separate Klassen unterteilt std :: future und std :: promise? In der Antwort auf diesen Post hieß es:

  

Der Grund, warum es in diese zwei getrennten "Schnittstellen" getrennt ist, ist   Verbergen Sie die Funktionalität "Schreiben / Setzen" vom "Consumer / Reader".

Ich verstehe nicht den Vorteil, sich hier zu verstecken. Aber ist es nicht einfacher, wenn wir nur eine Klasse "Zukunft" haben? Zum Beispiel: provive.set_value kann durch future.set_value ersetzt werden.

    
camino 09.12.2015, 02:08
quelle

2 Antworten

19

Das Problem, das Versprechen / Zukunft zu lösen gibt, besteht darin, einen Wert von einem Thread zum anderen zu hüten. Es kann stattdessen auch eine Ausnahme übertragen.

Der Quell-Thread muss also ein Objekt haben, mit dem er sprechen kann, um den gewünschten Wert an den anderen Thread zu senden. Ok ... wer besitzt dieses Objekt? Wenn die Quelle einen Zeiger auf etwas besitzt, das der Zielthread besitzt, woher weiß die Quelle, ob der Zielthread das Objekt gelöscht hat? Vielleicht kümmert sich der Ziel-Thread nicht mehr um den Wert. vielleicht hat sich so etwas geändert, dass es sich entschieden hat, einfach den Faden auf den Boden fallen zu lassen und es zu vergessen.

Das ist in einigen Fällen völlig legitim.

Nun stellt sich die Frage, warum die Quelle das Versprechen nicht besitzt und dem Ziel einfach einen Zeiger / Verweis darauf gibt? Nun, es gibt einen guten Grund dafür: Das Versprechen gehört dem Quell-Thread. Sobald der Quell-Thread beendet wird, wird das Versprechen zerstört. Dadurch wird der Ziel-Thread mit einem Verweis auf ein zerstörtes Versprechen verlassen.

Hoppla.

Daher besteht die einzige praktikable Lösung darin, zwei vollwertige Objekte zu haben: eines für die Quelle und eines für das Ziel. Diese Objekte teilen sich den Besitz des Werts, der übertragen wird. Das heißt natürlich nicht, dass sie nicht der gleiche -Typ sein könnten ; Du könntest etwas wie shared_ptr<promise> oder sowas haben. Immerhin muss "promise / future" internen Speicher haben, richtig?

Betrachten Sie jedoch die Schnittstelle von Versprechen / Zukunft, wie sie derzeit stehen.

promise kann nicht kopiert werden . Sie können verschieben , aber Sie können es nicht kopieren. future ist ebenfalls nicht kopierbar, aber ein future kann ein shared_future werden, das kopierbar ist. Sie können also mehrere Ziele haben, aber nur eine Quelle .

promise kann nur den Wert festlegen; es kann es nicht einmal zurückbekommen. future kann nur den Wert erhalten; es kann es nicht einstellen. Daher haben Sie eine asymmetrische Schnittstelle, die für diesen Anwendungsfall völlig geeignet ist. Sie möchten nicht, dass das Ziel den Wert und die Quelle festlegen kann, um es abrufen zu können. Das ist Rückwärts-Code-Logik.

Deshalb wollen Sie zwei Objekte. Sie haben eine asymmetrische Schnittstelle, die am besten mit zwei verwandten, aber separaten Typen und Objekten behandelt wird.

    
Nicol Bolas 09.12.2015, 02:47
quelle
4

Ich würde mir eine Zusage / Zukunft als eine asynchrone Warteschlange vorstellen (die nur einen einzelnen Wert enthalten soll).

Die Zukunft ist das Leseende der Warteschlange. Das Versprechen ist das Schreibende der Warteschlange.

Die Verwendung der beiden ist normalerweise unterschiedlich: Der Produzent schreibt normalerweise nur in die "Warteschlange", und der Verbrauch liest nur davon. Wie Sie bereits festgestellt haben, ist es für einen Hersteller möglich, den Wert zu lesen, aber dafür gibt es kaum einen Grund. Daher wird die Optimierung dieser speziellen Operation selten als Priorität angesehen.

Im üblichen Schema der Dinge produziert der Produzent den Wert und bringt ihn in das Versprechen. Der Verbraucher erhält den Wert aus der Zukunft. Jeder "Client" verwendet eine einfache Schnittstelle, die ausschließlich für eine einfache Aufgabe bestimmt ist, so dass es einfacher ist, den Code zu entwerfen und zu dokumentieren, sowie sicherzustellen, dass der Verbrauchercode nicht mit etwas in Zusammenhang steht, das mit der Erzeugung des Wertes zusammenhängt und umgekehrt). Ja, es ist möglich, das zu tun, aber genug zusätzliche Arbeit, dass es eher unwahrscheinlich ist, dass sie zufällig passiert.

    
Jerry Coffin 09.12.2015 02:48
quelle

Tags und Links