Skip to content

Async, Futures and Promises

Beginning of the lesson

Async, Futures and Promises

Getting results and exceptions back out of concurrent work

Big Idea: A raw 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.
By the end you will be able to:
  • use std::async to launch a task and read its result through a std::future,
  • choose deliberately between launch::async and launch::deferred,
  • wire a producer and consumer by hand with std::promise, including exceptions,
  • wrap any callable as a std::packaged_task to feed a thread pool,
  • avoid the classic pitfalls: the blocking ~future, one-shot get(), 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 a T (or an exception) here; get() retrieves it, blocking until it is ready.
  • std::promise<T> - a manual write end you fulfil yourself with set_value or set_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.
The shared state is a small heap-allocated block holding the result-or-exception, a "ready" flag, and synchronisation. The write end and the read end each hold a reference to it - conceptually much like the control block behind a shared_ptr.

Continue this lesson on YourAIZone

The full lesson has the complete explanation, worked examples, common mistakes, tests with instant checking and an AI tutor. Start right away as a guest, or create an account to keep your progress.

In the full lesson

  • The complete explanation
  • Worked examples
  • Common mistakes and how to avoid them
  • Test questions: 15
  • AI tutor that answers questions about the topic
  • Progress tracking for students, parents and teachers