@@ -18,9 +18,23 @@ type Limits struct {
1818 step time.Duration
1919}
2020
21+ // Peek glances there are enough resources (n) available.
22+ func (l * Limits ) Peek (n uint64 ) bool {
23+ l .mu .Lock ()
24+ defer l .mu .Unlock ()
25+ cycles := uint64 (time .Since (l .last ) / l .step )
26+ if cycles > 0 {
27+ l .last = l .last .Add (l .step * time .Duration (cycles ))
28+ doa .Doa (cycles <= math .MaxUint64 / l .addition )
29+ doa .Doa (l .size <= math .MaxUint64 - l .addition * cycles )
30+ l .size = l .size + l .addition * cycles
31+ l .size = min (l .size , l .capacity )
32+ }
33+ return l .size >= n
34+ }
35+
2136// Wait ensures there are enough resources (n) available, blocking if necessary.
2237func (l * Limits ) Wait (n uint64 ) {
23- doa .Doa (n < math .MaxUint64 / 2 )
2438 l .mu .Lock ()
2539 defer l .mu .Unlock ()
2640 cycles := uint64 (time .Since (l .last ) / l .step )
@@ -44,9 +58,8 @@ func (l *Limits) Wait(n uint64) {
4458// NewLimits creates a new rate limiter with rate r over period p.
4559func NewLimits (r uint64 , p time.Duration ) * Limits {
4660 doa .Doa (r > 0 )
47- doa .Doa (r < math .MaxUint64 / 2 )
4861 doa .Doa (p > 0 )
49- g := func (a , b uint64 ) uint64 {
62+ gcd := func (a , b uint64 ) uint64 {
5063 t := uint64 (0 )
5164 for b != 0 {
5265 t = b
@@ -55,14 +68,12 @@ func NewLimits(r uint64, p time.Duration) *Limits {
5568 }
5669 return a
5770 }(r , uint64 (p ))
58- a := r / g
59- s := p / time .Duration (g )
6071 return & Limits {
61- addition : a ,
72+ addition : r / gcd ,
6273 capacity : r ,
6374 last : time .Now (),
6475 mu : sync.Mutex {},
6576 size : r ,
66- step : s ,
77+ step : p / time . Duration ( gcd ) ,
6778 }
6879}
0 commit comments