2 분 소요

개요

  • promise
    • 복사 생성 불가
  • future
    • 객체 이동이 일어나므로 한번만 get 가능
  • shared_future
    • 복사가 가능하고 같은 객체를 공유
  • packaged_task
    • promise-future 패턴을 Callable의 반환값에 적용
    • packaged_task에 전달된 함수의 리턴값을 promise에 set_value 혹은 set_exception
    • packaged_task가 리턴하는 future를 통해 접근
    • 복사 생성 불가
  • async
    • 쓰레드를 자동으로 만들어서 전달된 함수를 수행하고 리턴값을 future에 전달
    • launch::async
      • 쓰레드를 바로 생성하여 전달된 함수 실행
    • launch::deferred
      • future의 get 함수가 호출되었을 때 쓰레드를 생성하지 않고 전달된 함수 실행


예제

  • make_unique를 사용함으로 C++14로 컴파일
  • 코드
    #include <chrono>
    #include <future>
    #include <iostream>
    #include <memory>
    #include <string>
    #include <thread>
    #include <vector>

    using namespace std;

    int main() {
        thread t1;
        thread t2;

        unique_ptr<promise<string>> p = make_unique<promise<string>>();
        future<string> f = p->get_future();

        t1 = thread([&p]() { p->set_value("data"); });
        t2 = thread([&f]() { cout << f.get() << endl; });
        t1.join();
        t2.join();

        cout << "------" << endl;

        p = make_unique<promise<string>>();
        f = p->get_future();
        t1 = thread([&p]() {
            try {
                throw runtime_error("runtime_error");
            } catch (...) {
                p->set_exception(current_exception());
            }
        });
        t2 = thread([&f]() {
            try {
                cout << f.get() << endl;
            } catch (const exception &e) {
                cout << e.what() << endl;
            }
        });
        t1.join();
        t2.join();

        cout << "------" << endl;

        p = make_unique<promise<string>>();
        f = p->get_future();
        t1 = thread([&p]() {
            this_thread::sleep_for(chrono::seconds(3));
            p->set_value("data");
        });
        t2 = thread([&f]() {
            while (true) {
                future_status status = f.wait_for(chrono::seconds(1));
                if (status == future_status::timeout) {
                    cout << "timeout" << endl;
                } else if (status == future_status::ready) {
                    cout << "ready : " << f.get() << endl;
                    break;
                } else if (status == future_status::deferred) {
                    cout << "deferred" << endl;
                }
            }
        });
        t1.join();
        t2.join();

        cout << "------" << endl;

        p = make_unique<promise<string>>();
        shared_future<string> sf = p->get_future();
        t1 = thread([&p]() { p->set_value("data"); });
        t2 = thread([sf]() {
            vector<thread> v;
            v.clear();

            for (int i = 0; i < 3; ++i) {
                v.push_back(thread([&sf]() { cout << sf.get() << endl; }));
            }

            for (auto &iter : v) {
                iter.join();
            }
        });
        t1.join();
        t2.join();

        cout << "------" << endl;

        packaged_task<string(int)> task([](int i) { return to_string(i); });
        f = task.get_future();
        t1 = thread(move(task), 1);
        t2 = thread([&f]() { cout << f.get() << endl; });
        t1.join();
        t2.join();

        cout << "------" << endl;

        cout << "main : " << this_thread::get_id() << endl;
        f = async(
            launch::async,
            [](int i) {
                cout << "async : " << this_thread::get_id() << endl;
                return to_string(i);
            },
            1);
        cout << f.get() << endl;

        cout << "------" << endl;

        cout << "main : " << this_thread::get_id() << endl;
        f = async(
            launch::deferred,
            [](int i) {
                cout << "async : " << this_thread::get_id() << endl;
                return to_string(i);
            },
            1);
        cout << f.get() << endl;

        return 0;
    }
  • 실행 결과
    data
    ------
    runtime_error
    ------
    timeout
    timeout
    ready : data
    ------
    data
    data
    data
    ------
    1
    ------
    main : 139688566888256
    async : 139688541705792
    1
    ------
    main : 139688566888256
    async : 139688566888256
    1