You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
1.4 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package common
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. /*
  7. ThrottleTimer fires an event at most "dur" after each .Set() call.
  8. If a short burst of .Set() calls happens, ThrottleTimer fires once.
  9. If a long continuous burst of .Set() calls happens, ThrottleTimer fires
  10. at most once every "dur".
  11. */
  12. type ThrottleTimer struct {
  13. Name string
  14. Ch chan struct{}
  15. quit chan struct{}
  16. dur time.Duration
  17. mtx sync.Mutex
  18. timer *time.Timer
  19. isSet bool
  20. }
  21. func NewThrottleTimer(name string, dur time.Duration) *ThrottleTimer {
  22. var ch = make(chan struct{})
  23. var quit = make(chan struct{})
  24. var t = &ThrottleTimer{Name: name, Ch: ch, dur: dur, quit: quit}
  25. t.mtx.Lock()
  26. t.timer = time.AfterFunc(dur, t.fireRoutine)
  27. t.mtx.Unlock()
  28. t.timer.Stop()
  29. return t
  30. }
  31. func (t *ThrottleTimer) fireRoutine() {
  32. t.mtx.Lock()
  33. defer t.mtx.Unlock()
  34. select {
  35. case t.Ch <- struct{}{}:
  36. t.isSet = false
  37. case <-t.quit:
  38. // do nothing
  39. default:
  40. t.timer.Reset(t.dur)
  41. }
  42. }
  43. func (t *ThrottleTimer) Set() {
  44. t.mtx.Lock()
  45. defer t.mtx.Unlock()
  46. if !t.isSet {
  47. t.isSet = true
  48. t.timer.Reset(t.dur)
  49. }
  50. }
  51. func (t *ThrottleTimer) Unset() {
  52. t.mtx.Lock()
  53. defer t.mtx.Unlock()
  54. t.isSet = false
  55. t.timer.Stop()
  56. }
  57. // For ease of .Stop()'ing services before .Start()'ing them,
  58. // we ignore .Stop()'s on nil ThrottleTimers
  59. func (t *ThrottleTimer) Stop() bool {
  60. if t == nil {
  61. return false
  62. }
  63. close(t.quit)
  64. t.mtx.Lock()
  65. defer t.mtx.Unlock()
  66. return t.timer.Stop()
  67. }