task.go 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package signal
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. // PeriodicTask is a task that runs periodically.
  7. type PeriodicTask struct {
  8. // Interval of the task being run
  9. Interval time.Duration
  10. // Execute is the task function
  11. Execute func() error
  12. access sync.Mutex
  13. timer *time.Timer
  14. closed bool
  15. }
  16. func (t *PeriodicTask) checkedExecute() error {
  17. t.access.Lock()
  18. defer t.access.Unlock()
  19. if t.closed {
  20. return nil
  21. }
  22. if err := t.Execute(); err != nil {
  23. return err
  24. }
  25. t.timer = time.AfterFunc(t.Interval, func() {
  26. t.checkedExecute()
  27. })
  28. return nil
  29. }
  30. // Start implements common.Runnable. Start must not be called multiple times without Close being called.
  31. func (t *PeriodicTask) Start() error {
  32. t.access.Lock()
  33. t.closed = false
  34. t.access.Unlock()
  35. if err := t.checkedExecute(); err != nil {
  36. t.closed = true
  37. return err
  38. }
  39. return nil
  40. }
  41. // Close implements common.Closable.
  42. func (t *PeriodicTask) Close() error {
  43. t.access.Lock()
  44. defer t.access.Unlock()
  45. t.closed = true
  46. if t.timer != nil {
  47. t.timer.Stop()
  48. t.timer = nil
  49. }
  50. return nil
  51. }