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