Choose a Pool
ThreadPool-FP ships two pool implementations with the same callback forms, error API, and lifecycle contract. Choose between them on one factor: do you need to bound the number of queued callbacks?
| If you need... | Start with... |
|---|---|
| Ordinary parallel work with the least setup | ThreadPool.Simple |
| A ready-to-use process-wide pool | GlobalThreadPool from ThreadPool.Simple |
| A private pool with a controlled worker count | TSimpleThreadPool.Create |
| A fixed queue capacity and submission deadlines | ThreadPool.ProducerConsumer |
| Fire-and-forget work only | Queue on either pool |
| A handle to wait for or cancel one task | Submit plus IThreadPoolTask |
| Bounded memory under a flood of work | ThreadPool.ProducerConsumer + TryQueue |
The two pools#
ThreadPool.Simple — unbounded queue#
- Dynamically growing FIFO: the queue never rejects work for capacity reasons.
QueueandTryQueueaccept immediately (unless shutdown has begun).- Suited to short bursts, job lists, range processing, and most applications.
- Memory grows with the backlog; there is no admission deadline.
ThreadPool.ProducerConsumer — bounded queue#
- Fixed-capacity circular queue (default 1024 callbacks).
Queuewaits while the queue is full and raisesEQueueFullExceptionif its compatibility deadline expires.TryQueue(..., TimeoutMS)returnsFalseon deadline instead of raising.- Suited to producers that can outrun consumers, streaming workloads, and anything where a bounded backlog matters.
Decision guide#
- Start with
GlobalThreadPool. It is process-wide, already exists, and covers most realistic workloads. - Choose
ThreadPool.ProducerConsumeronly when queue growth must be controlled or producers need a submission deadline. - Choose a private
TSimpleThreadPool.Create(N)pool when you need a fixed worker count or a lifetime independent of the global pool.
uses
ThreadPool.Simple, ThreadPool.Tasks;
begin
// A private unbounded pool with an explicit worker count.
SimplePool := TSimpleThreadPool.Create(4);
try
SimplePool.Queue(@DoWork);
SimplePool.WaitForAll;
finally
SimplePool.Free;
end;
// A bounded pool: 4 workers, queue capacity 1024.
BoundedPool := TProducerConsumerThreadPool.Create(4, 1024);
try
if not BoundedPool.TryQueue(@DoWork, 50) then
WriteLn('No queue space within 50 ms');
finally
BoundedPool.Free;
end;
end;Thread-count rules (both pools)#
| Constructor argument | Result |
|---|---|
0 (default) | TThread.ProcessorCount |
| below 4 | raised to 4 workers |
above 2 × ProcessorCount | capped at 2 × ProcessorCount |
Worker count is fixed after construction; neither pool scales dynamically.
Not a fit here?#
- ThreadPool-FP is not a task-scheduling framework: there are no priorities, futures, continuations, or automatic load balancing.
- Callbacks have no execution deadline and no forced interruption.
- For per-thread UI work or real-time guarantees, look elsewhere — worker callbacks run on pool threads and can block without a timeout.
See Contracts & Limitations for the precise boundaries.