timer.go 981 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package signal
  2. import (
  3. "context"
  4. "time"
  5. )
  6. type ActivityTimer interface {
  7. Update()
  8. }
  9. type realActivityTimer struct {
  10. updated chan bool
  11. timeout time.Duration
  12. ctx context.Context
  13. cancel context.CancelFunc
  14. }
  15. func (t *realActivityTimer) Update() {
  16. select {
  17. case t.updated <- true:
  18. default:
  19. }
  20. }
  21. func (t *realActivityTimer) run() {
  22. for {
  23. select {
  24. case <-time.After(t.timeout):
  25. case <-t.ctx.Done():
  26. return
  27. }
  28. select {
  29. case <-t.updated:
  30. // Updated keep waiting.
  31. default:
  32. t.cancel()
  33. return
  34. }
  35. }
  36. }
  37. func CancelAfterInactivity(ctx context.Context, timeout time.Duration) (context.Context, ActivityTimer) {
  38. ctx, cancel := context.WithCancel(ctx)
  39. timer := &realActivityTimer{
  40. ctx: ctx,
  41. cancel: cancel,
  42. timeout: timeout,
  43. updated: make(chan bool, 1),
  44. }
  45. go timer.run()
  46. return ctx, timer
  47. }
  48. type noOpActivityTimer struct{}
  49. func (noOpActivityTimer) Update() {}
  50. func BackgroundTimer() ActivityTimer {
  51. return noOpActivityTimer{}
  52. }