-
Notifications
You must be signed in to change notification settings - Fork 0
Avoiding Footguns
The lease/release contract is a balanced pair, and the pool trusts you to honor it. Like ArrayPool<T>.Return, it does not police misuse — it favors a tight, fast path over ownership tracking. These are the sharp edges and how to stay clear of them. A scoped lease closes the first two by construction; reach for it before the raw LeaseAsync/Release pair.
The pool tracks no ownership. Releasing the same item twice — or releasing an item the pool never handed you — enqueues a duplicate. After that, two callers can lease the same instance and corrupt each other's work. A double release also over-counts the capacity gate, which lets the pool create past MaxSize, or throws SemaphoreFullException when the gate is already full.
Release each leased item once, from a finally. Better, use LeaseScopeAsync: its return is idempotent, so a double dispose is a safe no-op.
A lease that never returns holds its capacity permit for the life of the pool. Leak MaxSize permits and the pool saturates: every later lease waits out the full LeaseTimeout and then throws. The try/finally is not optional. A scoped lease makes the return automatic, and a lease that is garbage-collected without being disposed is counted on the pool.leases.leaked counter — so even a slipped-through leak stays visible. See Metrics.
Disposing the pool disposes the items sitting idle in it. Items leased out at that moment belong to the caller — the pool cannot reclaim them, so dispose them yourself. After the pool is disposed, releasing an item to it throws ObjectDisposedException, as does leasing from it. A scoped lease handles the race for you: if the pool is disposed while an item is out on lease, disposing the lease disposes the orphaned item instead of returning it.
When a registered preparation strategy throws, the pool disposes that item rather than recirculate a broken one, frees the permit, and rethrows. The permit is not leaked — only the item is gone. Catch the exception at the call site and retry the lease for a fresh item.
- Leasing and releasing — the contract these edges come from, and the scoped-lease style that smooths most of them.
-
The capacity gate — why a stray release breaches
MaxSize, explained from the design.