Preliminary. ThinkMeta ConcurrentTasks and this documentation are preliminary; everything is subject to change.

When to use it

ConcurrentTasks pays off when work is split into many pieces that wait for each other or for I/O in the middle of their work. If your parallel work never waits, a plain thread pool or std::for_each with an execution policy may be all you need.

Good fits

  • Task graphs with dependencies. Stages that hand data to the next stage, serial stages that must see frames or blocks in order, parallel stages in between. Each stage waits for its input where it needs it — with a semaphore, an event or a task group — instead of being split into callbacks. The Task graphs guide shows the pattern.
  • Many simultaneous waits. Thousands of connections, files or timers, each handled by a task with straight-line code, served by a few threads.
  • Pipelines from disk to disk. Reading, computing and writing overlap because the reading and writing tasks are suspended while the I/O is in flight (Streaming large files).
  • Fine-grained parallelism with predictable cost. Suspending and resuming a task is a fiber switch, not a kernel transition; no allocation happens on the hot paths.

Poor fits

  • Long blocking calls into code you do not control. A task that blocks in an OS call or a third-party library blocks its scheduler thread. Run such work on its own threads, or use the asynchronous forms the library provides.
  • Millions of tasks waiting at once. Every suspended task keeps its fiber and stack. Thousands are fine; millions need a different design.
  • Platforms other than Windows x64.

Compared to …

Thread pool + callbacks C++ coroutines ConcurrentTasks
Waiting inside a task blocks a pool thread, or split the code into callbacks co_await, in every function up the call chain Wait() anywhere on the call stack; the thread runs other tasks
Memory per waiting task a thread (if it blocks) a coroutine frame a fiber with its stack
Code style inverted (continuations) colored functions ordinary sequential code
Scheduling FIFO pool depends on the executor work-stealing, two priorities, timers, I/O integrated

Next