Skip to content

Instantly share code, notes, and snippets.

@lxdlam
Created May 10, 2021 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lxdlam/7b555c5b9e743a6b36a58cb1d0eade5a to your computer and use it in GitHub Desktop.
Save lxdlam/7b555c5b9e743a6b36a58cb1d0eade5a to your computer and use it in GitHub Desktop.
A simple bucket based goroutine limiter
package main
import (
"fmt"
"sync"
"time"
)
type Limiter interface {
Commit(func())
Wait()
}
type tokenLimiter struct {
tokenChan chan bool
wg sync.WaitGroup
size int
}
func (tl *tokenLimiter) Commit(fn func()) {
// Acquire a token, blocking may happen
<-tl.tokenChan
go func() {
tl.wg.Add(1)
fn()
tl.wg.Done()
// We finish our work, produce a new token
tl.tokenChan <- true
}()
}
func (tl *tokenLimiter) Wait() {
tl.wg.Wait()
}
func NewTokenLimiter(size int) Limiter {
ch := make(chan bool, size)
// Make default tokens
for i := 0; i < size; i++ {
ch <- true
}
return &tokenLimiter{
tokenChan: ch,
wg: sync.WaitGroup{},
size: size,
}
}
func main() {
tl := NewTokenLimiter(2)
for i := 0; i < 10; i++ {
id := i
tl.Commit(func() {
fmt.Printf("Running task %d\n", id)
time.Sleep(time.Duration(100*(id+1)) * time.Millisecond)
})
}
tl.Wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment