10

Chapter 10 — Launch Policies and a packaged_task Worker Pool

std::async's default launch policy is a silent correctness gap, not a guarantee of concurrency — the only way to know whether a task actually ran concurrently is to ask it which thread it ran on.

Demo 10Source on GitHub ↗

The full source for this example lives in examples/concurrency/10-futures-promises-packaged-tasks/ — clone the repo, cd in, and ./demo.sh.

Chapter reference: Doc 10 — Futures, Promises, and Packaged Tasks

What it shows

One binary submits identical callables under std::launch::async, std::launch::deferred, and the default policy, with every callable reporting the thread id it actually executed on — async must always land on a thread distinct from the submitter, deferred must always run on the submitter’s own thread inside future::get(), and the default is reported without asserting a direction either way. A second binary is a small fixed-size thread pool built on std::packaged_task, where one task throws; that exception is rethrown intact at exactly that task’s own future::get(), and every other task’s result is unaffected. Both halves are checked as hard assertions, since they’re standard-mandated guarantees rather than performance claims a busy host could mute.

Running it

cd examples/concurrency/10-futures-promises-packaged-tasks
./demo.sh            # build + run launch_policy/worker_pool + verify.lua
./demo.sh --clean    # remove the image