-
Notifications
You must be signed in to change notification settings - Fork 402
/
limiter.go
50 lines (41 loc) · 950 Bytes
/
limiter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information
package sync2
import (
"context"
"sync"
)
// Limiter implements concurrent goroutine limiting
type Limiter struct {
limit chan struct{}
working sync.WaitGroup
}
// NewLimiter creates a new limiter with limit set to n
func NewLimiter(n int) *Limiter {
limiter := &Limiter{}
limiter.limit = make(chan struct{}, n)
return limiter
}
// Go tries to starts fn as a goroutine.
// When the limit is reached it will wait until it can run it
// or the context is canceled.
func (limiter *Limiter) Go(ctx context.Context, fn func()) bool {
select {
case limiter.limit <- struct{}{}:
case <-ctx.Done():
return false
}
limiter.working.Add(1)
go func() {
defer func() {
<-limiter.limit
limiter.working.Done()
}()
fn()
}()
return true
}
// Wait waits for all running goroutines to finish
func (limiter *Limiter) Wait() {
limiter.working.Wait()
}