개요
- promise
- future
- 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