limit.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package util
  2. import (
  3. "errors"
  4. "sync"
  5. )
  6. // ErrLimitReached is the error returned by the Limiter and LimitWriter when the predefined limit has been reached
  7. var ErrLimitReached = errors.New("limit reached")
  8. // Limiter is a helper that allows adding values up to a well-defined limit. Once the limit is reached
  9. // ErrLimitReached will be returned. Limiter may be used by multiple goroutines.
  10. type Limiter struct {
  11. value int64
  12. limit int64
  13. mu sync.Mutex
  14. }
  15. // NewLimiter creates a new Limiter
  16. func NewLimiter(limit int64) *Limiter {
  17. return &Limiter{
  18. limit: limit,
  19. }
  20. }
  21. // Add adds n to the limiters internal value, but only if the limit has not been reached. If the limit would be
  22. // exceeded after adding n, ErrLimitReached is returned.
  23. func (l *Limiter) Add(n int64) error {
  24. l.mu.Lock()
  25. defer l.mu.Unlock()
  26. if l.limit == 0 {
  27. l.value += n
  28. return nil
  29. } else if l.value+n <= l.limit {
  30. l.value += n
  31. return nil
  32. } else {
  33. return ErrLimitReached
  34. }
  35. }
  36. // Sub subtracts a value from the limiters internal value
  37. func (l *Limiter) Sub(n int64) {
  38. l.Add(-n)
  39. }
  40. // Set sets the value of the limiter to n. This function ignores the limit. It is meant to set the value
  41. // based on reality.
  42. func (l *Limiter) Set(n int64) {
  43. l.mu.Lock()
  44. l.value = n
  45. l.mu.Unlock()
  46. }
  47. // Value returns the internal value of the limiter
  48. func (l *Limiter) Value() int64 {
  49. l.mu.Lock()
  50. defer l.mu.Unlock()
  51. return l.value
  52. }
  53. // Limit returns the defined limit
  54. func (l *Limiter) Limit() int64 {
  55. return l.limit
  56. }