yohhoyの日記

技術的メモをしていきたい日記

futureとpromiseのあれこれ(実践編)

C++11標準ライブラリのstd::future<T>,std::promise<T>を実際に利用するときの注意点メモ。

gcc系共通の注意点として、g++オプションに「-std=c++0x -pthread」を指定する必要がある。前者はC++11機能サポートを有効に、後者はスレッド関連機能を有効にするオプション指定。-pthreadオプションを指定しないと、新スレッドの起動時にstd::system_error例外が投げられる。

Microsoft VisualC++は、2012年1月時点の最新版MSVC10でもC++11標準のスレッドライブラリをサポートしない。

下記コードをリファレンス実装として、(1), (2)箇所でのgcc各バージョンにおけるWorkaroundを説明していく。

#include <thread>
#include <future>

void func(std::promise<int> p)  // (1)
{
  p.set_value(42);
}

int call()
{
  std::promise<int> p;
  std::future<int> f = p.get_future();
  std::thread th(func, std::move(p));  // (2)
  th.detach();
  //...
  return f.get();
}

gcc 4.5

ライブラリ側実装の問題により、std::threadオブジェクトの関数func引数にrvalue referenceを渡すことができない。

#include <functional>

void func(std::promise<int> & p)  // (1') lvalue referenceで受ける必要がある
{ /*...*/ }

int call()
{
  //...
  std::thread th(func, std::ref(p));  // (2') std::move(p)ではコンパイルエラーのため参照渡しで回避
  //...
}

gcc 4.6

ライブラリ側実装の問題により、std::threadオブジェクトの関数func引数にrvalue referenceを渡しても、関数funcではlvalue referenceとして渡されてくる。このため、リファレンス実装(1)ではstd::promiseのコピーコンストラクタが呼ばれてしまい、同コンストラクタは削除指定されているためコンパイルエラーが発生する。

void func(std::promise<int> & p)  // (1') lvalue referenceで受ける必要がある
{ /*...*/ }

int call()
{
  //...
  std::thread th(func, std::move(p));  // (2) ムーブは可能だが...
  //...
}

gcc 4.7(experimental)

gcc 4.7 r176073 2011-07-09で修正が入り、リファレンス実装がそのまま通る。(注意:gcc 4.6以前のlvalue referenceで受けるWorkaroundがコンパイルエラーになる。)

void func(std::promise<int> p)  // (1) ムーブ(コンストラクト)されたオブジェクトで受ける
{ /*...*/ }

int main()
{
  //...
  std::thread th(func, std::move(p));  // (2) ムーブ可能
  //...
}

MSVC11(おまけ)

MSVC10は標準ヘッダ<thread>および<future>をサポートしないが、次期MSVC11ではサポートされるかも。(http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

サードパーティライブラリ

C++11標準スレッドライブラリ相当のサードパーティ製ライブラリとして、just::thread Pro C++ Concurrency Library by Just Software Solutions Ltdが販売されている。(使ったことないので情報だけ)

The upcoming C++ standard (C++0x) will support multithreading and concurrency both as an inherent part of the memory model, and as part of the C++ Standard Library.
With the just::thread C++ Standard Thread Library implementation, you can start using the C++0x thread library today — no need to wait for a new compiler.

Boost.Threadにも互換ライブラリが存在する。(std::futureにはboost::unique_futureが対応する)

関連URL