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.

72 lines
1.3 KiB

9 years ago
  1. package common
  2. import "time"
  3. import "sync"
  4. /*
  5. RepeatTimer repeatedly sends a struct{}{} to .Ch after each "dur" period.
  6. It's good for keeping connections alive.
  7. A RepeatTimer must be Stop()'d or it will keep a goroutine alive.
  8. */
  9. type RepeatTimer struct {
  10. Ch chan time.Time
  11. mtx sync.Mutex
  12. name string
  13. ticker *time.Ticker
  14. quit chan struct{}
  15. dur time.Duration
  16. }
  17. func NewRepeatTimer(name string, dur time.Duration) *RepeatTimer {
  18. var t = &RepeatTimer{
  19. Ch: make(chan time.Time),
  20. ticker: time.NewTicker(dur),
  21. quit: make(chan struct{}),
  22. name: name,
  23. dur: dur,
  24. }
  25. go t.fireRoutine(t.ticker)
  26. return t
  27. }
  28. func (t *RepeatTimer) fireRoutine(ticker *time.Ticker) {
  29. for {
  30. select {
  31. case t_ := <-ticker.C:
  32. t.Ch <- t_
  33. case <-t.quit:
  34. return
  35. }
  36. }
  37. }
  38. // Wait the duration again before firing.
  39. func (t *RepeatTimer) Reset() {
  40. t.Stop()
  41. t.mtx.Lock() // Lock
  42. defer t.mtx.Unlock()
  43. t.ticker = time.NewTicker(t.dur)
  44. t.quit = make(chan struct{})
  45. go t.fireRoutine(t.ticker)
  46. }
  47. // For ease of .Stop()'ing services before .Start()'ing them,
  48. // we ignore .Stop()'s on nil RepeatTimers.
  49. func (t *RepeatTimer) Stop() bool {
  50. if t == nil {
  51. return false
  52. }
  53. t.mtx.Lock() // Lock
  54. defer t.mtx.Unlock()
  55. exists := t.ticker != nil
  56. if exists {
  57. t.ticker.Stop()
  58. t.ticker = nil
  59. close(t.quit)
  60. }
  61. return exists
  62. }