reugn / equalizer

A set of performant rate limiters for Go

Home Page:https://pkg.go.dev/github.com/reugn/equalizer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

tokenBucket: incorrect count of issued when refill

rschio opened this issue · comments

// refill refills the token bucket.
func (tb *tokenBucket) refill() {
issued := atomic.LoadInt32(&tb.issued)
atomic.StoreInt32(&tb.issued, 0)
tb.fillTokenBucket(int(issued))
}
// Ask requires a permit.
// It is a non blocking call, returns true or false.
func (tb *TokenBucket) Ask() bool {
select {
case <-tb.t.permits:
atomic.AddInt32(&tb.t.issued, 1)
return true

A token can be issued between line 68 and 69 and then it will lead to a incorrect issued count and decrease the bucket real capacity.

Example:
refill() and Ask() executes concurrently then:
line 68 executes
line 77 and 78 executes
line 69 and 70 executes

Solution:
issued := atomic.SwapInt32(&tb.issued, 0)

@rschio thanks.