Beispiel #1
0
        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());
            }
        }
Beispiel #2
0
        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());
            }
        }