- 스레드 사이에서 "값 또는 예외를 공유" 할 수 있는 템플릿
- promise를 통해서 전달된 데이터는 std::future<> 를 통해서 얻을 수 있다.
- 스레드 생성시 promise 객체를 "참조(&, &&) 로 전달" 한다.
void add(std::promise<int>&& p, int a, int b)
{
int s = a + b;
std::this_thread::sleep_for(1s);
//p.set_value(s);
p.set_value_at_thread_exit(s); // 쓰레드가 끝날때 값을 전해라.
}
int main()
{
std::promise<int> pm;
std::future<int> ft = pm.get_future();
std::thread t(add, std::move(pm), 10, 20);
int ret = ft.get(); // blocking
std::cout << ret << std::endl;
t.join();
}
- set_value 는 한번만 사용할 수 있다.
- future() 는 한번만 꺼낼 수 있다.
- 여러 개가 필요하다면 shared_future 사용.
예외 전달
void divide(std::promise<int>&& p, int a, int b)
{
try
{
// c++ 에서 0으로 나누면 경고만 나오고 exception이 발생하지는 않는다.
if (b == 0)
throw std::runtime_error("divide by zero");
p.set_value(a / b);
}
catch(...)
{
// 현재 발생한 exception을 셋팅한다.
// p.set_exception( std::current_exception() );
// 쓰레드가 종료될때 값을 전달하라.
p.set_exception_at_thread_exit( std::current_exception() );
}
}
int main()
{
std::promise<int> pm;
std::future<int> ft = pm.get_future();
std::thread t(divide, std::move(pm), 10, 0);
try
{
// get을 호출할때 exception이 지정되었다면 똑같이 throw 한다.
int ret = ft.get(); // blocking
}
catch(std::exception& e)
{
std::cout << e.what() << std::endl;
}
t.join();
}
void를 이용한 동기화 작업(베리어)
int main()
{
std::vector<int> v1 = { 1, 2, 3, 4, 5 }
std::vector<int> v2(10);
std::promise<void> pm1;
std::future<void> ft1 = pm1.get_future();
std::promise<int> pm2;
std::future<int> ft2 = pm2.get_future();
std::thread t( [&]{
std::partial_sum(v1.begin(), v1.end(), v2.begin());
// void 버전은 인자값이 필요 없다.
pm1.set_value(); // 첫번째 연산이 종료되었음을 알린다.
int s = std::accumulate(v2.begin(), v2.end(), 0);
pm2.set_value(s);
});
ft1.get(); // 첫 번째 연산이 완료될때까지 기다린다.
for (auto n : v2)
std::cout << n << ", ";
int ret = ft2.get(); // 두 번째 연산이 완료될때까지 기다린다.
t.join();
}
std::future