2016-03-22 3 views
1

Was ich tun möchte ist, einen Wert aus jedem Thread zurückzugeben. Es hat jedoch diese Ausnahmebedingungsnachricht.C++ mehrere Rückgabewerte von Thread mit Versprechen, Zukunft?

libc++abi.dylib: terminating with uncaught exception of type std::__1::future_error: Operation not permitted on an object without an associated state. 

Der Code sieht so aus.

vector<thread> t; 
promise<class_name> promises; 
vector<future<class_name>> futures; 

for(int i = 0; i < NumberOfThreads; i++) 
{ 
    futures.push_back(promises.get_future()); 
    t.push_back(thread(MyFunction ,i , pointList, std::move(promises))); 
} 

und die MyFunction sieht so aus.

void MyFunction(int index, const vector<Point>& pointList, promise<class_name>&& p) 
{ 
.... 
p.set_value(classObj); 
} 

Wenn ich einen Thread verwende, dann funktioniert es gut ohne Ausnahme Nachricht.

Irgendeine Idee, um dieses Problem zu lösen?

Antwort

3

Verwenden Sie das Versprechen nicht erneut, nachdem Sie es in seinen Thread verschoben haben. Bewegen Sie das Versprechen innerhalb der Schleife und der Code sollte gut laufen:

vector<thread> t; 
vector<future<class_name>> futures; 

for(int i = 0; i < NumberOfThreads; i++) 
{ 
    promise<class_name> p; 
    futures.push_back(p.get_future()); 
    t.push_back(thread(MyFunction ,i , pointList, std::move(p))); 
} 
1

Wenn Sie

tun
std::promise<T> p; 

Sie ein Versprechen erstellen p mit einem leeren gemeinsamen Staat. Dies ist anders als kein gemeinsamer Status.

Wenn Sie sich von einem Versprechen bewegen, wird der gemeinsame Status übernommen. So

std::promise<T> p2=std::move(p); 

jetzt p hat keinen Staat geteilt und p2 hat den leer gemeinsamen Staat dass p mit konstruiert.

Wenn Sie push_back in einen Container, es tut etwas analog zu der obigen Konstruktion (möglicherweise wiederholt).

p ist jetzt eine äußerst nutzlose Variable. Es kann zerstört werden, oder es kann zugewiesen werden, oder es kann swap Ed mit einem anderen Versprechen sein. Alle anderen Vorgänge unter p sind illegal.

Eine Funktion wie:

template<class T> 
void reset_promise(std::promise<T>& p) { 
    p = std::promise<T>{}; 
} 

könnte verwendet werden, p einen leeren gemeinsamen Staat zu geben. Angesichts des typischen Nutzungsmusters einer promise sehe ich jedoch nicht viel Sinn.

std::vector<std::thread> t; 
std::promise<class_name> promises; 
std::vector<std::future<class_name>> futures; 

for(int i = 0; i < NumberOfThreads; i++) 
{ 
    futures.push_back(promises.get_future()); 
    t.push_back(thread(MyFunction ,i , pointList, std::move(promises))); 
} 

auf der ersten Schleife, bewegen Sie sich aus dem Versprechen. In der zweiten Schleife versuchen Sie get_future von einem Versprechen, das verschoben wurde, und Ihr Code macht etwas illegal.

Entweder:

for(int i = 0; i < NumberOfThreads; i++) 
{ 
    futures.push_back(promises.get_future()); 
    t.push_back(thread(MyFunction ,i , pointList, std::move(promises))); 
    reset_promise(promises); 
} 

, wenn Sie wirklich die promises Variable oder

std::vector<std::thread> t; 
std::vector<std::future<class_name>> futures; 

for(int i = 0; i < NumberOfThreads; i++) 
{ 
    std::promise<class_name> promises; 
    futures.push_back(promises.get_future()); 
    t.push_back(thread(MyFunction ,i , pointList, std::move(promises))); 
} 

wird wiederverwenden möchten sicherstellen, dass Sie eine gültige promise an dem Punkt, wo Sie es verwenden. Die zweite ist wahrscheinlich in diesem Fall am besten: Versprechungen werden in einem kleinen Umfang konstruiert, verwendet und verworfen.

Grundsätzlich, promise s wo gemacht, um optimal zu sein für das Erstellen, extrahieren Zukunft, verschieben Versprechen, wo es benötigt wird, verwerfen Muster. Wenn ein versetztes Versprechen einen gemeinsamen Status hat, würden Ressourcen kosten (da dieser gemeinsame Status normalerweise auf dem Heap gespeichert wird), so dass sie es nicht getan haben.

Verwandte Themen