What is ConcurrentTasks?
ConcurrentTasks runs your work as tasks on a scheduler: a set of OS threads, by default one per logical processor. Each task runs on a fiber. When a task has to wait, it is suspended — its fiber is set aside together with its stack — and the thread continues with another task. When the reason for the wait is gone, the task is resumed and continues right after the call that waited.
That is the whole idea: waiting costs a task, not a thread.
Important
A resumed task continues on any thread of its scheduler — not necessarily the one it was
suspended on. Code in a task must not carry thread-bound state across a wait: no OS lock
(std::mutex, CRITICAL_SECTION, SRWLOCK) held over a Wait, no thread_local values, no
thread id, no COM single-threaded apartment or window that belongs to the thread. Use the
library's primitives instead; its CriticalSection is owned by the task,
not by the thread. See Tasks.
Two layers
| Layer | What it is | Ships as |
|---|---|---|
| Core | The scheduler, the timer thread and the I/O completion port. A C interface: create a scheduler, add tasks, suspend and resume them, enable timers and asynchronous I/O. | ThinkMeta.ConcurrentTasks.Core.dll (a few KB, imports only KERNEL32) and the header Core.h |
| Library | C++ modules built on the core: task base classes, events, semaphores, critical sections, task groups, lock-free collections, virtual-memory pipes, asynchronous files and sockets. | Source code you compile into your project |
The library has no special access to the core: everything it does goes through Core.h, so you
can write your own primitives the same way (see Custom primitives).
What a task can do
- Wait for other tasks — WaitableTask, TaskGroup.
- Synchronize — AutoResetEvent, ManualResetEvent, Semaphore, CriticalSection. They suspend the waiting task, never the thread.
- Wait with a time limit and sleep — once timers are enabled (EnableTimers).
- Read and write files and sockets — the operation is started, the task is suspended, and the core's I/O thread resumes it when the operation completes (AsyncFile, AsyncTcpSocket).
- Yield and change its priority — YieldTask, SetTaskPriority.
Any function on the task's call stack may wait; nothing has to be rewritten as callbacks or coroutines.
What it is not
- Not a thread pool with callbacks. Tasks are ordinary sequential code that waits in place.
- Not portable. It is built on Windows fibers and I/O completion ports and runs on Windows x64.
- Not defensive. It trusts the caller. See Performance first.
Where it comes from
ConcurrentTasks is the scheduler behind ThinkMeta's encoders ctLame, ctJpeg, ctOpus and ctDeflate, which spread the work on a single file over all cores and write exactly the same bytes as their sequential references. Their task graphs are described step by step on the product pages, for example ctLame.