미래와 약속은 비동기 작업의 두 가지 측면입니다.
std::promise
비동기 작업의 "제작자 / 작성자"가 사용합니다.
std::future
비동기 작업의 "소비자 / 리더"에서 사용합니다.
이 두 개의 "인터페이스"로 분리 된 이유 는 "소비자 / 판독자"에서 "쓰기 / 설정"기능 을 숨기기 때문입니다.
auto promise = std::promise<std::string>();
auto producer = std::thread([&]
{
promise.set_value("Hello World");
});
auto future = promise.get_future();
auto consumer = std::thread([&]
{
std::cout << future.get();
});
producer.join();
consumer.join();
std :: promise를 사용하여 std :: async를 구현하는 하나의 (불완전한) 방법은 다음과 같습니다.
template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
typedef decltype(func()) result_type;
auto promise = std::promise<result_type>();
auto future = promise.get_future();
std::thread(std::bind([=](std::promise<result_type>& promise)
{
try
{
promise.set_value(func()); // Note: Will not work with std::promise<void>. Needs some meta-template programming which is out of scope for this question.
}
catch(...)
{
promise.set_exception(std::current_exception());
}
}, std::move(promise))).detach();
return std::move(future);
}
std::packaged_task
어떤 도우미를 사용하면 (즉, 기본적으로 우리가 위에서하고있는 일을 수행합니다) std::promise
더 완전하고 가능하면 더 빠른 다음을 수행 할 수 있습니다.
template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
auto task = std::packaged_task<decltype(func())()>(std::forward<F>(func));
auto future = task.get_future();
std::thread(std::move(task)).detach();
return std::move(future);
}
이것은 실제로 스레드가 끝날 때까지 실제로 블록을 막을 때 std::async
반환 되는 위치와 약간 다릅니다 std::future
.