Updated:

2 minute read

개요

  • 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