2016-03-22 37 views
1

我想要做的是從每個線程返回一個值。但是,它有這個例外信息。C++多線程返回值使用promise,future?

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

代碼如下所示。

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))); 
} 

和MyFunction看起來像這樣。

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

如果我使用一個線程,那麼它工作正常,沒有例外消息。

任何想法來解決這個問題?

回答

3

在您將其移至線程後,不要重複使用該承諾。移動循環體中的承諾,你的代碼應該運行良好:

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

當你

std::promise<T> p; 

您創建一個承諾p空的共享狀態。這與沒有共享狀態不同。

當您從承諾中移出時,將採用共享狀態。所以

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

現在p已經沒有共享狀態p2空的共享狀態p與構建。

當您將push_back放入容器中時,它會執行與上述構造類似的操作(可能會重複)。

p現在是一個非常無用的變量。它可以被銷燬,也可以分配給它,也可以與另一個承諾一起使用。 p上的所有其他操作都是非法的。

的函數,如:

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

可以用來給p空共享狀態。但是,鑑於promise的典型使用模式,我沒有看到太多的觀點。

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))); 
} 

在第一個循環中,您將移出承諾。在第二個循環中,您嘗試從已移出的承諾中嘗試get_future,並且您的代碼執行某些非法操作。

或者:

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); 
} 

如果你真的想重用promises變量,或

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))); 
} 

將確保您在您使用它的點有一個有效promise。第二種情況在這種情況下可能是最好的:承諾在小範圍內構建,使用和丟棄。

基本上,promise s在哪裏做了最佳的創建,提取未來,移動到需要的地方,丟棄模式。有一個共享狀態會有一個共享狀態會花費資源(因爲共享狀態通常存儲在堆中),所以他們沒有這樣做。