N2671 - 非同期 Future Value

そういえば大分前に翻訳して貼ってなかったので。

http://melpon.tank.jp/pukiwiki147/index.php?Memo%2F%CB%DD%CC%F5%2FN2671%20-%20An%20Asynchronous%20Future%20Value%A1%A7%20Proposed%20Wording


概念的には、マルチスレッドデザインパターンの Future パターンと全く同じで、値の設定は promise クラスの set_value()、値の取得は unique_future か shared_future の get() から行います。
promise の set_exception() で例外を設定することも可能で、例外をセットすると、unique_future, shared_future の get() で例外が発生します。


unique_future と shared_future の違いは、get() するときに設定されたデータを move するか参照を返して貰うかという違いだけです。内部のデータを move するので、unique_future の2回目以降の get() 呼び出しは unspecified です。


多分使い方はこんな感じ。

struct task
{
private:
    std::promise<int> p_;
public:
    task() { }
    task(task&& t) : p_(std::move(t.p_)) { }
    task(const task&) = delete;

    void operator()()
    {
        try
        {
            p_.set_value(do_something());
        }
        catch (...)
        {
            p_.set_exception(std::current_exception());
        }
    }
    // ここに裏スレッドで行いたい処理を書いて、結果を返す
    int do_something();

    std::unique_future<int> get_future() { return p_.get_future(); }
};
// 裏スレッドで task を実行する関数
std::unique_future<int> do_task()
{
    task t;
    std::unique_future<int> res(t.get_future());
    std::thread(std::move(t));
    return res;
}
// 裏スレッドで処理を行う
std::unique_future<int> future = do_task();

// 何か別の処理をする
...

// 裏スレッドの結果が本当に必要になったので取得する
// もし裏スレッドの処理が終わってない場合は、その処理が終わるのを待つ
try
{
    int result = future.get();
    std::cout << result << std::endl;
}
catch (...)
{
    std::cout << "error" << std::endl;
}

ちなみに packaged_task は削除されたとか書いてるけど、この後の N2709 で復活してます。
↑の処理も packaged_task を使えばもっと簡単に書けるようになるので、後日書きます。