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();
}

예외 전달

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