Exemplo n.º 1
0
        /// <summary>
        /// Attempt to consume a specified number of tokens from the bucket.  If the tokens were consumed then <code>true</code>
        /// is returned, otherwise <code>false</code> is returned.
        /// </summary>
        /// <param name="numTokens">The number of tokens to consume from the bucket, must be a positive number.</param>
        /// <returns><code>true</code> if the tokens were consumed, <code>false</code> otherwise.</returns>
        public bool TryConsume(long numTokens)
        {
            if (numTokens <= 0)
            {
                throw new ArgumentOutOfRangeException("numTokens", "Number of tokens to consume must be positive");
            }
            if (numTokens > _capacity)
            {
                throw new ArgumentOutOfRangeException("numTokens", "Number of tokens to consume must be less than the capacity of the bucket.");
            }

            lock (_syncRoot)
            {
                // Give the refill strategy a chance to add tokens if it needs to, but beware of overflow
                var newTokens = Math.Min(_capacity, Math.Max(0, _refillStrategy.Refill()));
                _size = Math.Max(0, Math.Min(_size + newTokens, _capacity));

                if (numTokens > _size)
                {
                    return(false);
                }

                // Now try to consume some tokens
                _size -= numTokens;
                return(true);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Attempts to consume the specified number of tokens from the bucket. If the
        /// requested number of tokens are not immediately available, then this method
        /// will return false to indicate that zero tokens have been consumed.
        /// </summary>
        public bool TryConsume(long tokens)
        {
            if (tokens <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(tokens),
                                                      "Number of tokens to consume must be positive"
                                                      );
            }

            if (tokens > Capacity)
            {
                throw new ArgumentOutOfRangeException(nameof(tokens),
                                                      "Number of tokens to consume must be less than or equal to the capacity"
                                                      );
            }

            lock (_sync)
            {
                // determine how many units have become available since last invocation
                var refilled = Math.Max(0, _refill.Refill());

                // the number of tokens to add, the max of which is the difference between capacity and currently available
                var deltaTokens = Math.Min(Capacity - _available, refilled);

                // update the available number of units with the new tokens
                _available += deltaTokens;

                if (tokens > _available)
                {
                    // we don't have enough tokens yet
                    Logging.Log.Trace($"LeakyBucket.TryConsume({tokens}): Failed to consumed tokens. Available: {_available}");
                    return(false);
                }

                // subtract the number of tokens consumed
                _available = _available - tokens;
                Logging.Log.Trace($"LeakyBucket.TryConsume({tokens}): Successfully consumed tokens. Available: {_available}");
                return(true);
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Sometimes the bucket is half-used before we start counting. This allows us
 /// to account for this in the beginning.
 /// </summary>
 public void SetRemainingTokens(long numTokens)
 {
     lock (_syncRoot)
         _refillStrategy.Refill();
     _size = numTokens;
 }