std::promise
提供: cppreference.com
<tbody>
</tbody>
| ヘッダ <future> で定義
|
||
template< class R > class promise; |
(1) | (C++11以上) |
template< class R > class promise<R&>; |
(2) | (C++11以上) |
template<> class promise<void>; |
(3) | (C++11以上) |
1) 基本テンプレート
2) スレッド間でオブジェクトをやり取りするために使用される非 void 特殊化
3) ステートレスなイベントをやり取りするための void 特殊化
クラステンプレート std::promise は、 std::promise オブジェクトによって作成された std::future オブジェクトを通して後に非同期に取得される、値または例外を格納する機能を提供します。 std::promise オブジェクトは一度しか使用できないことに注意してください。
各々のプロミスは「共有状態」に紐付いています。 共有状態は何らかの状態情報と、「まだ評価されていない」「値 (void も有り得る) に評価された」「例外に評価された」のいずれかの「結果」を持ちます。 プロミスは共有状態を使用して以下の3つのことをします。
- 準備完了状態にする: 共有状態に結果または例外を格納します。 状態を準備完了に設定し、共有状態に紐付いているフューチャーで待機しているあらゆるスレッドのブロックを解除します。
- 解放する: 共有状態への参照を放棄します。 これが最後の参照であった場合、その共有状態は破棄されます。 これが
std::asyncによって作成された準備完了していない共有状態でない限り、この操作はブロックしません。 - 放棄する: エラーコード std::future_errc::broken_promise を持った std::future_error 型の例外を格納します。 これにより共有状態は準備完了になり、そして解放されます。
プロミスはプロミスとフューチャーの通信チャネルの「プッシュ」側の端点です。 共有状態に値を格納する操作は、その共有状態で待機する任意の関数 (std::future::get など) からの成功による戻りに対して同期します (std::memory_order を参照してください)。 それ以外では、同じ共有状態への並行アクセスは衝突する可能性があります。 例えば、 std::shared_future::get の呼び出し元が複数ある場合は、そのすべてが読み込み専用であるか、外部の同期を使用するかの、いずれかでなければなりません。
メンバ関数
| プロミスオブジェクトを構築します (パブリックメンバ関数) | |
| プロミスオブジェクトを破棄します (パブリックメンバ関数) | |
| 共有状態を代入します (パブリックメンバ関数) | |
| 2つのプロミスオブジェクトを入れ替えます (パブリックメンバ関数) | |
結果の取得 | |
| 約束された結果に紐付けられた future を返します (パブリックメンバ関数) | |
結果の設定 | |
| 特定の値に結果を設定します (パブリックメンバ関数) | |
| スレッド終了時にのみ通知が配送されるように特定の値に結果を設定します (パブリックメンバ関数) | |
| 例外を表す結果を設定します (パブリックメンバ関数) | |
| スレッド終了時にのみ通知が配送されるように例外を表す結果を設定します (パブリックメンバ関数) | |
非メンバ関数
(C++11) |
std::swap アルゴリズムの特殊化 (関数テンプレート) |
ヘルパークラス
| std::uses_allocator 型特性の特殊化 (クラステンプレートの特殊化) |
例
この例はスレッド間の信号として promise<int> をどのように使用できるかを示します。
Run this code
#include <vector>
#include <thread>
#include <future>
#include <numeric>
#include <iostream>
#include <chrono>
void accumulate(std::vector<int>::iterator first,
std::vector<int>::iterator last,
std::promise<int> accumulate_promise)
{
int sum = std::accumulate(first, last, 0);
accumulate_promise.set_value(sum); // フューチャーに通知します。
}
void do_work(std::promise<void> barrier)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
barrier.set_value();
}
int main()
{
// スレッド間で結果を転送するために promise<int> の使用をデモンストレーションします。
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6 };
std::promise<int> accumulate_promise;
std::future<int> accumulate_future = accumulate_promise.get_future();
std::thread work_thread(accumulate, numbers.begin(), numbers.end(),
std::move(accumulate_promise));
// future::get() はフューチャーが有効な結果を保持するまで待ちます。
// get() の前に wait() を呼ぶ必要はありません。
//accumulate_future.wait(); // 結果を待ちます。
std::cout << "result=" << accumulate_future.get() << '\n';
work_thread.join(); // スレッドの終了を待ちます。
// スレッド間で状態を通知するために promise<void> の使用をデモンストレーションします。
std::promise<void> barrier;
std::future<void> barrier_future = barrier.get_future();
std::thread new_work_thread(do_work, std::move(barrier));
barrier_future.wait();
new_work_thread.join();
}
出力:
result=21