-
Notifications
You must be signed in to change notification settings - Fork 0
IPool API
IPool<TPoolItem> is the surface you inject. It declares three operations, a set of diagnostic counters, and implements IDisposable. TPoolItem is constrained to a reference type (where TPoolItem : class). For usage guidance, see Leasing and releasing; this page is the signature-level reference.
The signatures below describe the default bounded pool. The unbounded pool implements the same interface with a looser contract: LeaseAsync never waits or throws TaskCanceledException (there is no MaxSize or LeaseTimeout), Release is optional, and QueuedLeases is always 0. The differences are called out per member below.
ValueTask<TPoolItem> LeaseAsync();
ValueTask<TPoolItem> LeaseAsync(CancellationToken cancellationToken);Borrows an item. Returns an idle item, creates one if the pool is below MaxSize, or waits for a release until LeaseTimeout elapses or the token is canceled. The parameterless overload uses CancellationToken.None.
- Throws
ObjectDisposedExceptionwhen the pool is disposed. - Throws
TaskCanceledExceptionwhenLeaseTimeoutelapses. - Throws
OperationCanceledExceptionwhencancellationTokenis canceled.
In an unbounded pool a lease never waits — it returns an idle item or creates one — so it never throws TaskCanceledException. It still throws OperationCanceledException for an already-canceled token and during preparation.
void Release(TPoolItem item);Returns a leased item. If a lease is waiting, the item is handed to it directly; otherwise it becomes idle. Synchronous by design — the return enqueues the item and frees a permit, neither of which awaits.
- Throws
ArgumentNullExceptionwhenitemis null. - Throws
ObjectDisposedExceptionwhen the pool is disposed.
Release each leased item exactly once. The pool tracks no ownership; a double release corrupts the pool — see Avoiding footguns.
In an unbounded pool release is optional: a lease transfers ownership, so a returned item is kept for reuse up to MaxIdle and dropped past it. An item you never return is not reused, and disposing it becomes your responsibility.
void Clear();Disposes every idle item, then refills the pool to MinSize, capped by free capacity so it never exceeds MaxSize. Leased items are unaffected and re-enter on release. Queued lease requests are served by those returns, not by this call.
- Throws
ObjectDisposedExceptionwhen the pool is disposed.
LeaseScopeAsync is an extension method in PoolLeaseExtensions, not a member of the interface. It wraps a lease in a disposable Lease<TPoolItem>:
ValueTask<Lease<TPoolItem>> LeaseScopeAsync<TPoolItem>(
this IPool<TPoolItem> pool,
CancellationToken cancellationToken = default)
where TPoolItem : class;Lease<TPoolItem> exposes the item and returns it on dispose:
-
Item— the leased item. ThrowsObjectDisposedExceptionafter the lease is disposed. -
Dispose()— returns the item to the pool exactly once; idempotent. If the pool was disposed while the item was out on lease, the item is disposed here instead.
A Lease garbage-collected without being disposed is recorded on the pool.leases.leaked counter. See Leasing and releasing.
All counters are read-only and derived from live pool state.
-
int ItemsAllocated— items the pool owns, leased plus idle. -
int ItemsAvailable— allocated items that are idle and not leased. -
int ActiveLeases— items currently leased out (ItemsAllocatedminusItemsAvailable). -
int QueuedLeases— lease requests waiting for a release. Always0for an unbounded pool. -
string Name— the pool name, of the form"{typeof(TPoolItem).Name}.Pool", or"{typeof(TPoolItem).Name}.UnboundedPool"for an unbounded pool.
For production observability, prefer the Metrics instruments over polling these.
IPool<TPoolItem> is IDisposable. Disposing the pool disposes its idle items only; items leased out at that moment belong to the caller. See Avoiding footguns.