public ValueTask <int> RequestCreditAsync(int amount, CancellationToken cancellationToken) { lock (SyncObject) { if (_disposed) { throw new ObjectDisposedException($"{nameof(CreditManager)}:{_owner.GetType().Name}:{_name}"); } // If we can satisfy the request with credit already available, do so synchronously. if (_current > 0) { Debug.Assert(_waitersTail is null, "Shouldn't have waiters when credit is available"); int granted = Math.Min(amount, _current); if (NetEventSource.IsEnabled) { _owner.Trace($"{_name}. requested={amount}, current={_current}, granted={granted}"); } _current -= granted; return(new ValueTask <int>(granted)); } if (NetEventSource.IsEnabled) { _owner.Trace($"{_name}. requested={amount}, no credit available."); } // Otherwise, create a new waiter. CreditWaiter waiter = cancellationToken.CanBeCanceled ? new CancelableCreditWaiter(SyncObject, cancellationToken) : new CreditWaiter(); waiter.Amount = amount; // Add the waiter at the tail of the queue. if (_waitersTail is null) { _waitersTail = waiter.Next = waiter; } else { waiter.Next = _waitersTail.Next; _waitersTail.Next = waiter; _waitersTail = waiter; } // And return a ValueTask<int> for it. return(waiter.AsValueTask()); } }
public ValueTask <int> RequestCreditAsync(int amount, CancellationToken cancellationToken) { lock (SyncObject) { // If we can satisfy the request with credit already available, do so synchronously. int granted = TryRequestCreditNoLock(amount); if (granted > 0) { return(new ValueTask <int>(granted)); } if (NetEventSource.Log.IsEnabled()) { _owner.Trace($"{_name}. requested={amount}, no credit available."); } // Otherwise, create a new waiter. CreditWaiter waiter = cancellationToken.CanBeCanceled ? new CancelableCreditWaiter(SyncObject, cancellationToken) : new CreditWaiter(); waiter.Amount = amount; // Add the waiter at the tail of the queue. if (_waitersTail is null) { _waitersTail = waiter.Next = waiter; } else { waiter.Next = _waitersTail.Next; _waitersTail.Next = waiter; _waitersTail = waiter; } // And return a ValueTask<int> for it. return(waiter.AsValueTask()); } }