private bool TryLeaseUnsynchronized(int permitCount, [NotNullWhen(true)] out RateLimitLease?lease) { // if permitCount is 0 we want to queue it if there are no available permits if (_permitCount >= permitCount && _permitCount != 0) { if (permitCount == 0) { // Edge case where the check before the lock showed 0 available permits but when we got the lock some permits were now available lease = SuccessfulLease; return(true); } // a. if there are no items queued we can lease // b. if there are items queued but the processing order is newest first, then we can lease the incoming request since it is the newest if (_queueCount == 0 || (_queueCount > 0 && _options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst)) { _permitCount -= permitCount; Debug.Assert(_permitCount >= 0); lease = new ConcurrencyLease(true, this, permitCount); return(true); } } lease = null; return(false); }
private void Release(int releaseCount) { lock (Lock) { _permitCount += releaseCount; Debug.Assert(_permitCount <= _options.PermitLimit); while (_queue.Count > 0) { RequestRegistration nextPendingRequest = _options.QueueProcessingOrder == QueueProcessingOrder.OldestFirst ? _queue.PeekHead() : _queue.PeekTail(); if (_permitCount >= nextPendingRequest.Count) { nextPendingRequest = _options.QueueProcessingOrder == QueueProcessingOrder.OldestFirst ? _queue.DequeueHead() : _queue.DequeueTail(); _permitCount -= nextPendingRequest.Count; _queueCount -= nextPendingRequest.Count; Debug.Assert(_queueCount >= 0); Debug.Assert(_permitCount >= 0); ConcurrencyLease lease = nextPendingRequest.Count == 0 ? SuccessfulLease : new ConcurrencyLease(true, this, nextPendingRequest.Count); // Check if request was canceled if (!nextPendingRequest.Tcs.TrySetResult(lease)) { // Queued item was canceled so add count back _permitCount += nextPendingRequest.Count; } nextPendingRequest.CancellationTokenRegistration.Dispose(); } else { break; } } } }