[C++] promise, future, packaged_task, async
Updated:
개요
- 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