1package libkbfs
2
3import "context"
4
5// OngoingWorkLimiter limits maximum number of routines that can work on a same
6// type of thing at the same time. For example, it can be used for limiting
7// number of ongoing rekeys.
8type OngoingWorkLimiter struct {
9	permits chan struct{}
10}
11
12// NewOngoingWorkLimiter creates a new *OngoingWorkLimiter with capacity of
13// maxNumOngoingWorks.
14func NewOngoingWorkLimiter(maxNumOngoingWorks int) *OngoingWorkLimiter {
15	return &OngoingWorkLimiter{
16		permits: make(chan struct{}, maxNumOngoingWorks),
17	}
18}
19
20// WaitToStart blocks until the limiter would allow one more routine to start
21// working on the thing.
22func (owl *OngoingWorkLimiter) WaitToStart(ctx context.Context) error {
23	select {
24	case owl.permits <- struct{}{}:
25		return nil
26	case <-ctx.Done():
27		return ctx.Err()
28	}
29}
30
31// Done tells the limiter that the caller is done working on the thing, and
32// somebody else is free to start work.
33func (owl *OngoingWorkLimiter) Done() {
34	<-owl.permits
35}
36