release method

void release()

Releases one permit; hands it directly to the next waiter if any, otherwise returns it to the available pool. Audited: 2026-06-12 11:26 EDT

Implementation

void release() {
  // Direct hand-off: when a waiter is queued the permit transfers to it
  // WITHOUT touching `_available` (the slot was never freed to the pool). Only
  // increment when there is no waiter to take the permit.
  if (_waiters.isNotEmpty) {
    _waiters.removeAt(0)();
  } else {
    // Guard the permit invariant: with no waiter and the pool already full,
    // this release has no matching acquire. Incrementing would push
    // `_available` above `permits` and let the semaphore admit more than
    // `permits` concurrent holders forever. Fail loud instead of silently
    // corrupting the count.
    if (_available >= permits) {
      throw StateError('release() called without a matching acquire() (permits: $permits)');
    }
    _available++;
  }
}