The thread pool
- Cost
- Waking or waiting for a thread costs one mutex and one condition-variable operation; requesting threads scans the pool under a lock.
Creating a thread is expensive compared with many of the subcomputations that FLINT runs in parallel. FLINT therefore creates its threads once, in flint_set_num_threads, and keeps them asleep in a pool between uses. This is the classical thread-pool design for POSIX threads [But1997].
Thread states#
Each thread of a pool has an entry with a mutex, two condition variables (sleep1, on which the thread waits for work, and sleep2, on which the owner waits for completion), the function to run with its argument, a working flag, an available flag and an exit flag.
| State | Set by | Meaning |
|---|---|---|
| available | thread_pool_init, thread_pool_give_back | free to be handed out |
| unavailable, sleeping | thread_pool_request, end of a function | owned by a caller, idle |
| unavailable, working | thread_pool_wake | running a function |
Every thread runs thread_pool_idle_loop:
- Lock the entry. Set
workingto 0. - If
exitis set, unlock and terminate. - Signal
sleep2(waking a caller waiting inthread_pool_wait) and wait onsleep1, releasing the lock while waiting. - If
workingis still 0, the wake-up was spurious: go to step 2. - Unlock. Set this thread's worker budget to the
max_workersvalue it was woken with, run the function, and go to step 1.
thread_pool_wake sets the function, its argument and the budget, sets working to 1 and signals sleep1, all under the entry's lock. thread_pool_wait waits on sleep2 until working is 0. Testing the flag after every wake-up, rather than trusting the signal, is what makes the protocol immune to spurious wake-ups and to a signal arriving before the other side waits [But1997, Chapter 3].
Worker budgets#
The pool itself does not know how many threads a computation may use. Instead every thread has a thread-local worker budget: the number of further workers it may start. flint_get_num_threads() returns the budget plus one.
- The master thread's budget is set by
flint_set_num_threads(n)to n - 1. - A thread woken with
thread_pool_wake(..., max_workers, ...)gets the budgetmax_workerswhile it runs. flint_set_num_workerslowers the budget of the calling thread temporarily, andflint_reset_num_workersrestores it.
A parallel function that may use t threads requests up to t - 1 workers. If it obtains w of them, it divides its remaining budget among itself and the workers it wakes. When every function follows this rule, the number of threads working on one top-level call never exceeds the budget of the caller plus one. Independently of the budgets, the number of running threads never exceeds the pool size plus one, since threads are only ever borrowed from the pool.
Requesting threads#
thread_pool_request scans the entries in order under the pool's mutex and takes the first available ones. A caller may receive fewer threads than it asked for, or none, when other threads hold parts of the pool. FLINT's parallel functions treat the number of threads as a hint: the work is split according to the threads actually obtained, and the result does not depend on it.
Resizing and affinity#
thread_pool_set_size succeeds only when every thread is available. It tells all threads to exit, joins them, and creates the new set, so its cost is that of creating the threads anew. thread_pool_set_affinity pins the calling thread and the pool's threads to given processors with pthread_setaffinity_np, where available; the original affinity of the creating thread is recorded at initialisation and can be restored.
slong thread_pool_request(thread_pool_t T, thread_pool_handle * out, slong requested)void thread_pool_wake(thread_pool_t T, thread_pool_handle i, int max_workers, void (*f)(void*), void * a)void thread_pool_wait(thread_pool_t T, thread_pool_handle i)void flint_set_num_threads(int num_threads)slong flint_request_threads(thread_pool_handle ** handles, slong thread_limit)Referenced from#
- Parallel loops and binary splitting (algorithm)
- thread_pool.h (module)
- Using the thread pool directly
References#
- [But1997] D. R. Butenhof, Programming with POSIX Threads, Addison-Wesley (1997)
The FLINT team, “The thread pool,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/parallel/thread-pool.html (generated 2026-10-20).
@misc{flint-doc-algorithms-parallel-thread-pool,
author = {{The FLINT team}},
title = {{The thread pool}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/parallel/thread-pool.html},
note = {Generated 2026-10-20}
}