447 Stimmen

Was ist std::promise?

Ich bin ziemlich vertraut mit C++11's std::thread , std::async et std::future Komponenten (siehe z.B. diese Antwort ), die einfach zu handhaben sind.

Ich kann jedoch nicht ganz nachvollziehen, was std::promise ist, was es bewirkt und in welchen Situationen es am besten eingesetzt werden kann. Das Standarddokument selbst enthält außer der Klassenzusammenfassung nicht viele Informationen, und auch die std::thread .

Könnte jemand bitte ein kurzes, prägnantes Beispiel für eine Situation nennen, in der ein std::promise benötigt wird und wo es die sinnvollste Lösung ist?

211voto

Jonathan Wakely Punkte 159417

In den Worten von [futures.state] ein std::future ist ein asynchrones Rückgabeobjekt ("ein Objekt, das Ergebnisse aus einem gemeinsamen Zustand liest") und ein std::promise ist ein asynchroner Anbieter ("ein Objekt, das ein Ergebnis für einen gemeinsamen Zustand liefert"), d.h. ein Versprechen ist das, was Sie einstellen. ein Ergebnis an, so dass Sie erhalten. es aus der damit verbundenen Zukunft.

Der asynchrone Anbieter erstellt zunächst den gemeinsamen Zustand, auf den sich ein Future bezieht. std::promise ist ein Typ eines asynchronen Anbieters, std::packaged_task ist eine andere, und das interne Detail von std::async ist eine andere. Jedes dieser Elemente kann einen gemeinsamen Zustand schaffen und Ihnen eine std::future der diesen Zustand teilt, und kann den Zustand bereit machen.

std::async ist ein übergeordnetes Dienstprogramm, das Ihnen ein asynchrones Ergebnisobjekt liefert und sich intern um die Erstellung des asynchronen Anbieters und die Bereitstellung des gemeinsamen Zustands bei Beendigung der Aufgabe kümmert. Man könnte es mit einer std::packaged_task (oder std::bind und eine std::promise ) und eine std::thread aber es ist sicherer und einfacher zu benutzen std::async .

std::promise ist etwas einfacher, wenn Sie ein asynchrones Ergebnis an die Zukunft übergeben wollen, aber der Code, der das Ergebnis bereitstellt, kann nicht in einer einzigen Funktion verpackt werden, die zur Übergabe an std::async . Sie könnten zum Beispiel ein Array mit mehreren promise s und zugehörige future s und haben einen einzigen Thread, der mehrere Berechnungen durchführt und für jedes Versprechen ein Ergebnis festlegt. async nur ein einziges Ergebnis zurückgeben würde, müssten Sie für mehrere Ergebnisse async mehrmals, was zu einer Verschwendung von Ressourcen führen kann.

40voto

Paul Rubel Punkte 25730

Bartosz Milewski bietet eine gute Zusammenfassung.

C++ unterteilt die Implementierung von Futures in eine Reihe von von kleinen Blöcken

std::promise ist einer dieser Teile.

Ein Versprechen ist ein Vehikel zur Übergabe des Rückgabewerts (oder einer Ausnahme) von dem Thread, der eine Funktion ausführt, an den Thread der die Zukunft der Funktion einlöst.

...

Ein future ist das Synchronisationsobjekt, das um die Empfangsende des Versprechenskanals aufgebaut ist.

Wenn Sie also eine Zukunft verwenden möchten, erhalten Sie ein Versprechen, das Sie verwenden, um das Ergebnis der asynchronen Verarbeitung zu erhalten.

Ein Beispiel auf der Seite ist:

promise<int> intPromise;
future<int> intFuture = intPromise.get_future();
std::thread t(asyncFun, std::move(intPromise));
// do some other stuff
int result = intFuture.get(); // may throw MyException

32voto

In einer groben Annäherung kann man Folgendes berücksichtigen std::promise als das andere Ende einer std::future (dies ist falsch aber zur Veranschaulichung können Sie so tun, als wäre es so). Auf der Verbraucherseite des Kommunikationskanals würde ein std::future um die Daten aus dem gemeinsamen Zustand zu konsumieren, während der Producer-Thread eine std::promise um in den gemeinsamen Zustand zu schreiben.

15voto

kjp Punkte 3046

std::promise ist der Kanal oder Pfad für Informationen, die von der asynchronen Funktion zurückgegeben werden. std::future ist der Synchronisationsmechanismus, der den Aufrufer warten lässt, bis der Rückgabewert, der in der std::promise bereit ist (d. h. sein Wert wird innerhalb der Funktion festgelegt).

8voto

Zack Yezek Punkte 1332

Bei der asynchronen Verarbeitung gibt es im Grunde 3 Hauptkomponenten. C++11 konzentriert sich derzeit auf 2 von ihnen.

Die wichtigsten Dinge, die Sie benötigen, um eine Logik asynchron auszuführen, sind:

  1. En Aufgabe (Logik verpackt als ein Funktor-Objekt), das "irgendwo" LÄUFT.

  2. En tatsächlicher Verarbeitungsknoten - ein Thread, ein Prozess usw., der solche Funktoren AUSFÜHRT, wenn sie ihm zur Verfügung gestellt werden. Schauen Sie sich das "Command"-Entwurfsmuster an, um eine gute Vorstellung davon zu bekommen, wie ein einfacher Worker-Thread-Pool dies tut.

  3. En Ergebnis Griff : Jemand braucht dieses Ergebnis, und er braucht ein Objekt, das es für ihn GET. Aus OOP- und anderen Gründen sollte jegliches Warten oder Synchronisieren in den APIs dieses Handles erfolgen.

C++11 nennt die Dinge, von denen ich in (1) spreche std::promise und die in (3) std::future . std::thread ist das einzige, was öffentlich für (2) zur Verfügung gestellt wird. Das ist bedauerlich, denn echte Programme müssen Thread- und Speicherressourcen verwalten, und die meisten wollen, dass Aufgaben in Thread-Pools ausgeführt werden, anstatt für jede kleine Aufgabe einen Thread zu erstellen und zu zerstören (was fast immer unnötige Leistungseinbußen verursacht und leicht zu einer Ressourcenverknappung führen kann, die noch schlimmer ist).

Laut Herb Sutter und anderen Mitgliedern des C++11-Brain-Trusts gibt es vorläufige Pläne, eine std::executor die - ähnlich wie in Java - die Grundlage für Thread-Pools und logisch ähnliche Setups für (2) bilden werden. Vielleicht werden wir das in C++2014 sehen, aber ich tippe eher auf C++17 (und Gott steh uns bei, wenn sie den Standard für diese Dinge verpfuschen).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X