Last active
November 7, 2019 18:39
-
-
Save senojj/bd24ebbb3adabf6ce41aa954d99d2d03 to your computer and use it in GitHub Desktop.
A throttle implementation in Go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dyn | |
import ( | |
"time" | |
) | |
// A Throttle holds a channel that delivers a number of 'leases' at intervals. | |
type Throttle struct { | |
C <-chan time.Time // The channel on which the leases are delivered. | |
done chan struct{} | |
} | |
// NewThrottle returns a new Throttle containing a channel that will send the time x number | |
// of times within a period specified by the duration argument. It drops leases to make up | |
// for slow receivers. The duration must be greater than zero; if not, NewThrottle will | |
// panic. Stop the throttle to release associated resources and close its channel. | |
func NewThrottle(x int, duration time.Duration) *Throttle { | |
ch := make(chan time.Time, x - 1) | |
done := make(chan struct{}, 1) | |
go func() { | |
ticker := time.NewTicker(duration) | |
now := time.Now() | |
for i := 0; i < x - 1; i++ { | |
ch <- now | |
} | |
loop: | |
for { | |
select { | |
case t := <-ticker.C: | |
for i := 0; i < x; i++ { | |
select { | |
case ch <- t: | |
default: | |
} | |
} | |
case <-done: | |
break loop | |
} | |
} | |
ticker.Stop() | |
close(ch) | |
}() | |
return &Throttle{C: ch, done: done} | |
} | |
// Stop turns off a throttle. After Stop, no more leases will be sent. Stop closes the | |
// channel. | |
func (t *Throttle) Stop() { | |
select { | |
case t.done <- struct{}{}: | |
default: | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment