Tools — Pool
Everything reusable lives here.
A Pool gives out items for reuse, instead of allocating fresh ones in a hot loop.
What a Pool does
A Pool gives out items for reuse instead of a fresh allocation every time.
new(hooks) — into a Slot, then take the pointer out
↓
empty pool
get() [pool empty] get() [pool has items]
↓ a fresh item is created ↓ an item is reused
with caller with caller
put() [kept] put() [destroyed]
↓ ↓
back in the pool caller frees it
close()
↓ every stored item is given back for the caller to free
getgives a handle to the caller — reused if one is free, freshly made otherwise.putreturns the handle — the Pool decides whether to keep it or let it go.closecollects everything still held and passes it to youron_closehook, which releases it.
A Pool resource is an empty container
A Pool is not storage.
- Getting an item back tells you nothing about what it holds — that's up to your hooks.
putcan keep the item as-is.putcan keep it after resetting its data.putcan delete it.putcan delete it and hand back a different item instead.- Nothing you
putin is guaranteed to still be there on the nextget. - No fixed count/order/identity survives a put/get sequence unless your hooks guarantee it.
-
See API Reference — Pool for the four
putoutcomes. -
A Pool resource alone never defines a complete pattern.
- Useful work always needs at least one other input too: a Mailbox message, a network read, a timer tick, some shared state.
The Pool touches items — through your hooks
This is the difference from a Mailbox, which never touches an
Item at all. A Pool creates, resets, keeps or destroys — but every one of
those is your hook doing it, never the Pool deciding on its own.
A closed Pool gives items back
A Pool does not care whether you closed it either. Only destroy insists,
and panics on an open Pool.
puton a closed Pool is a no-op and leaves the Slot unchanged.put_allstops at the first refusal and leaves the rest in your list.
Either way you still hold those Items and must release them. So check the
Slot after put, and check the list after put_all.
Closing releases through on_close, not through you — the other difference
from a Mailbox, which returns the list to the caller and leaves the
releasing to them.
An empty Pool is a signal, not an error
- When nothing is free, the caller waits — that's backpressure, not a failure.
- No separate rate limiter, no manual throttling code.
- One event loop watches "a Mailbox message arrived" and "a Pool item became free" side by side. A worker returns an item — whoever was waiting resumes.
A worker pool, end to end, in Matryoshka-Tk notation:
[ Worker ] >>> get() >>> { Job Processor }
| uses the Worker
[ Worker ] <<< put() <<< { Job Processor }
If [ Worker ] is empty when get() is called, { Job Processor } waits.
That wait ends the moment some other { Job Processor } calls put().
See also: API Reference — Pool for the actual Zig functions.