Async, Futures and Promises
Getting results and exceptions back out of concurrent work
std::thread can run work, but it returns nothing and any exception it throws crashes the program. The futures library adds a one-way channel called the shared state: a producer eventually writes a value (or an exception) into it, and a consumer reads that value out through a std::future, blocking only when it actually needs the result. This decouples starting work from collecting its result.
- use
std::asyncto launch a task and read its result through astd::future, - choose deliberately between
launch::asyncandlaunch::deferred, - wire a producer and consumer by hand with
std::promise, including exceptions, - wrap any callable as a
std::packaged_taskto feed a thread pool, - avoid the classic pitfalls: the blocking
~future, one-shotget(), and silent deferral.
1. Why raw threads are not enough
You already know std::thread from the concurrency basics. Its callable returns void as far as the thread is concerned: there is no built-in way to get a value back, and if the task throws, the exception cannot cross the thread boundary, so the runtime calls std::terminate. To return a result manually you would need a shared variable plus a std::mutex and a std::condition_variable to signal "it is ready" - a lot of error-prone plumbing for something as ordinary as "run this and give me the answer".
The <future> header packages exactly that plumbing behind a clean interface. Three cooperating pieces sit on top of one hidden shared state:
std::future<T>- the read end. Someone will eventually put aT(or an exception) here;get()retrieves it, blocking until it is ready.std::promise<T>- a manual write end you fulfil yourself withset_valueorset_exception.std::async/std::packaged_task- convenience producers that create the write end for you from a callable and fill it with the callable's return value automatically.
shared_ptr.