|
@@ -145,7 +145,6 @@ func (r *Reservation) DelayFrom(now time.Time) time.Duration {
|
|
|
// Cancel is shorthand for CancelAt(time.Now()).
|
|
|
func (r *Reservation) Cancel() {
|
|
|
r.CancelAt(time.Now())
|
|
|
- return
|
|
|
}
|
|
|
|
|
|
// CancelAt indicates that the reservation holder will not perform the reserved action
|
|
@@ -186,8 +185,6 @@ func (r *Reservation) CancelAt(now time.Time) {
|
|
|
r.lim.lastEvent = prevEvent
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- return
|
|
|
}
|
|
|
|
|
|
// Reserve is shorthand for ReserveN(time.Now(), 1).
|
|
@@ -309,15 +306,27 @@ func (lim *Limiter) SetBurstAt(now time.Time, newBurst int) {
|
|
|
// reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN.
|
|
|
func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation {
|
|
|
lim.mu.Lock()
|
|
|
+ defer lim.mu.Unlock()
|
|
|
|
|
|
if lim.limit == Inf {
|
|
|
- lim.mu.Unlock()
|
|
|
return Reservation{
|
|
|
ok: true,
|
|
|
lim: lim,
|
|
|
tokens: n,
|
|
|
timeToAct: now,
|
|
|
}
|
|
|
+ } else if lim.limit == 0 {
|
|
|
+ var ok bool
|
|
|
+ if lim.burst >= n {
|
|
|
+ ok = true
|
|
|
+ lim.burst -= n
|
|
|
+ }
|
|
|
+ return Reservation{
|
|
|
+ ok: ok,
|
|
|
+ lim: lim,
|
|
|
+ tokens: lim.burst,
|
|
|
+ timeToAct: now,
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
now, last, tokens := lim.advance(now)
|
|
@@ -354,7 +363,6 @@ func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duratio
|
|
|
lim.last = last
|
|
|
}
|
|
|
|
|
|
- lim.mu.Unlock()
|
|
|
return r
|
|
|
}
|
|
|
|
|
@@ -367,36 +375,31 @@ func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time,
|
|
|
last = now
|
|
|
}
|
|
|
|
|
|
- // Avoid making delta overflow below when last is very old.
|
|
|
- maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens)
|
|
|
- elapsed := now.Sub(last)
|
|
|
- if elapsed > maxElapsed {
|
|
|
- elapsed = maxElapsed
|
|
|
- }
|
|
|
-
|
|
|
// Calculate the new number of tokens, due to time that passed.
|
|
|
+ elapsed := now.Sub(last)
|
|
|
delta := lim.limit.tokensFromDuration(elapsed)
|
|
|
tokens := lim.tokens + delta
|
|
|
if burst := float64(lim.burst); tokens > burst {
|
|
|
tokens = burst
|
|
|
}
|
|
|
-
|
|
|
return now, last, tokens
|
|
|
}
|
|
|
|
|
|
// durationFromTokens is a unit conversion function from the number of tokens to the duration
|
|
|
// of time it takes to accumulate them at a rate of limit tokens per second.
|
|
|
func (limit Limit) durationFromTokens(tokens float64) time.Duration {
|
|
|
+ if limit <= 0 {
|
|
|
+ return InfDuration
|
|
|
+ }
|
|
|
seconds := tokens / float64(limit)
|
|
|
- return time.Nanosecond * time.Duration(1e9*seconds)
|
|
|
+ return time.Duration(float64(time.Second) * seconds)
|
|
|
}
|
|
|
|
|
|
// tokensFromDuration is a unit conversion function from a time duration to the number of tokens
|
|
|
// which could be accumulated during that duration at a rate of limit tokens per second.
|
|
|
func (limit Limit) tokensFromDuration(d time.Duration) float64 {
|
|
|
- // Split the integer and fractional parts ourself to minimize rounding errors.
|
|
|
- // See golang.org/issues/34861.
|
|
|
- sec := float64(d/time.Second) * float64(limit)
|
|
|
- nsec := float64(d%time.Second) * float64(limit)
|
|
|
- return sec + nsec/1e9
|
|
|
+ if limit <= 0 {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ return d.Seconds() * float64(limit)
|
|
|
}
|