スレッドをまたいで値や例外を受け渡すには、std::promise および std::future または std::shared_future を使用します。
これらのクラスについて使用例などを記載したいと思います。
スレッド間で非同期に値や例外を受け渡す方法として、std::promise および std::future というクラスが提供されています。
あるスレッドで std::promise クラスのオブジェクトに値や例外を設定すると、それを別のスレッドで std::future クラスのオブジェクトを通してスレッドセーフに受け取ることができます。
子のサンプルでは、作成したスレッド worker 上で架空の計算を行ったものとして計算結果 42 を std::promise オブジェクト p へ設定します。もしくは計算中に例外を発生した場合、発生した例外を std::promise オブジェクト p へ設定します。メインスレッドはその計算結果が終わるのを待って計算結果を受け取っています。もしくは計算中に発生した例外を受け取ります。
これらのクラスは、マルチスレッドだけではなくシングルスレッドで非同期処理を行う場合にも利用できます。
コンパイラ : | g++ (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 | |
OS : | Ubuntu 24.04.2 LTS (WSL) | |
#include <iostream> #include <thread> #include <future> #include <exception> void worker(std::promise<int> p) { try{ std::this_thread::sleep_for(std::chrono::seconds(10)); //throw std::runtime_error("Worker thread error"); // 例外を発生させる p.set_value(42); // 値をセット } catch (...) { p.set_exception(std::current_exception()); // 発生した例外をセット } } int main() { std::promise<int> p; std::future<int> f = p.get_future(); // worker関数を別スレッドで実行 std::thread t(worker, std::move(p)); try{ std::cout << "値を待っています..." << std::endl; int result = f.get(); // 値がセットされるまで待つ std::cout << "受け取った値: " << result << std::endl; } catch (std::exception& e) { std::cout << "例外が発生しました: " << e.what() << std::endl; } t.join(); return 0; }
前章では別タスクの演算結果をf.get()で取得していました。意図通りの動作ではありますが、せっかく別タスクで計算を行っているのに演算結果の取得待ちになるので別タスクで演算しているかいがありません。別タスクで計算を行っている間にさらに別の作業を行えるようにしたいと思います。
std::future::wait_forという非同期操作の進捗を待つ際に便利なメソッドがあります。これを使用すると、指定した期間中に非同期操作が完了したかどうかを確認できます。
コンパイラ : | g++ (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 | |
OS : | Ubuntu 24.04.2 LTS (WSL) | |
#include <iostream> #include <thread> #include <future> #include <exception> void worker(std::promise<int> p) { try{ std::this_thread::sleep_for(std::chrono::seconds(10)); //throw std::runtime_error("Worker thread error"); // 例外を発生させる p.set_value(42); // 値をセット } catch (...) { p.set_exception(std::current_exception()); // 発生した例外をセット } } int main() { std::promise<int> p; std::future<int> f = p.get_future(); // worker関数を別スレッドで実行 std::thread t(worker, std::move(p)); try{ std::cout << "値を待っています..." << std::endl; while(f.wait_for(std::chrono::seconds(1)) != std::future_status::ready) { std::cout << "まだ値がセットされていません..." << std::endl; } // 値がセットされた int result = f.get(); // 値を取得 std::cout << "受け取った値: " << result << std::endl; } catch (std::exception& e) { std::cout << "例外が発生しました: " << e.what() << std::endl; } t.join(); return 0; }
実行結果
値を待っています... まだ値がセットされていません... まだ値がセットされていません... まだ値がセットされていません... まだ値がセットされていません... まだ値がセットされていません... まだ値がセットされていません... まだ値がセットされていません... まだ値がセットされていません... まだ値がセットされていません... 受け取った値: 42
本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。
2025-05-31 | - | 新規作成 |