2016-03-22 12 views
1

私がしたいのは、各スレッドから値を返すことです。ただし、この例外メッセージがあります。将来の約束を使用してスレッドからのC++多重戻り値?

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

プロミスをスレッドに移動した後に再使用しないでください。ループ本体内部の約束を移動して、あなたのコードは正常に実行する必要があります:あなたは

std::promise<T> p; 

を行うと

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

はあなたが空の共有状態と約束pを作成します。これは、に共有状態がないとは異なります

約束事から移動すると、共有状態になります。だから、

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

は今p無共有状態を持っており、p2pを用いて構築されたことを空の共有状態を持っています。

コンテナにpush_backを置くと、これは上記の構造に類似しています(おそらく繰り返します)。

pは非常に役に立たない変数です。それは破壊することができる、またはそれに割り当てることができる、または別の約束でswapにすることができます。 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))); 
} 

、あなたは約束の外に移動。 2番目のループでは、移動した約束からget_futureを試してみると、あなたのコードは違法なことをしています。

どちらか:あなたは本当にpromises変数を再利用する場合

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

、または

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を持っていることを確認します。 2番目の方がおそらくこの場合に最適です。約束事は、小さな範囲で構築され、使用され、廃棄されます。

基本的には、promiseここでは、作成に最適化され、未来を抽出し、必要な場所に約束し、パターンを破棄します。共有から解放された約束を持つと共有リソースはリソースを消費することになり(通常共有リソースはヒープに格納されるため)、リソースを使用しませんでした。

関連する問題