2016-05-31 7 views
3

Ist es sicher, eine std::future aus einer std::packaged_task zu erstellen, die auf einem separaten Thread ausgeführt wird, aber nicht immer das Ergebnis abrufen?Ist es sicher, das Ergebnis eines std :: future von einer std :: packaged_task nie zu erhalten?

#include <future> 
#include <thread> 

class Result { 
    Result() {} 
    ~Result() {} 
}; 

void foo() { 
    std::packaged_task<Result()> task(..); 
    auto future = task.get_future(); 
    std::thread thread(std::move(task), ...); 
    thread.detach(); 
    if (future.wait_for(std::chrono::milliseconds(timeout_ms)) == std::future_status::ready) { 
    auto result = future.get(); <--- Task didn't take too long, retrieve future result 
    ... 
    } 
} <--- Task is taking too long, just abort and never call future.get() 

Es scheint auf Clang/libc arbeiten ++: ~Result() auf das zurückgegebene Ergebnis durch die std::packaged_task ob oder nicht get() schließlich auf dem std::future genannt genannt wird, aber da ich etwas in der C++ docs nicht finden konnte, über Dieses Nutzungsmuster würde ich gerne sicherstellen, dass es offiziell unterstützt wird.

Antwort

0

Es kommt darauf an ... was Sie als sicher für Ihr Programm betrachten.
Für den Kontext Sie gezeigt haben, ist es sicher wie in:

  • Es blockiert nicht, wenn die future vor einem get auf sie zerstört tut. Wenn die Zukunft mit std::async erstellt wurde und Sie get nicht aufrufen, bevor es zerstört wird, hätte es blockiert, bis das Ergebnis verfügbar war.
    Schauen Sie sich mehr auf das hier: http://en.cppreference.com/w/cpp/thread/future/~future

diese Aktionen blockieren nicht für den gemeinsamen Staat bereit zu werden, außer dass es blockiert, wenn alle der folgenden Bedingungen erfüllt sind: der gemeinsame Staat erstellt durch einen Aufruf von std :: async, der freigegebene Zustand ist noch nicht bereit, und dies war die letzte Referenz auf den freigegebenen Zustand.

Nun, was ist, wenn die Result Klasse eine Nicht-Besitz wurde Haltespeicher (aus irgendeinem Grund) oder einer anderen Ressource, die manuell freigegeben werden muss. In diesem Fall wird die Korrektheit Ihres Codes fraglich. Eine bessere Sache wäre es, sie in einen Hintergrundthread für langsame Aufgaben zu schicken.

+0

Ich hatte das Blockierungsverhalten mit 'std :: async' tatsächlich bemerkt, deshalb bin ich zu' std :: packaged_task' gewechselt. Ich bin mir nicht sicher, was Sie mit "Korrektheit Ihres Codes wird fraglich" gemeint? Solange '~ Result()' garantiert vom anderen Status aufgerufen wird, was könnte dann schiefgehen? – Pol

+0

In der Tat haben Sie Recht, wenn Ihre Result-Klasse den Speicher besitzen soll. Aber selten müssen Sie keine Daten mehr besitzen. In solchen Fällen wäre es falsch zu vergessen, "get_future" aufzurufen. Wenn es mit Zweck gemacht wird (wie in Ihrem Beispiel), dann ist es wahrscheinlich in Ordnung, wenn die Ressource von RAII übernommen wird. – Arunmu

Verwandte Themen