timers.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
  2. package loop
  3. import (
  4. "fmt"
  5. "slices"
  6. "time"
  7. "kitty/tools/tty"
  8. "kitty/tools/utils"
  9. )
  10. var debugprintln = tty.DebugPrintln
  11. var _ = debugprintln
  12. type timer struct {
  13. interval time.Duration
  14. deadline time.Time
  15. repeats bool
  16. id IdType
  17. callback TimerCallback
  18. }
  19. func (self *timer) update_deadline(now time.Time) {
  20. self.deadline = now.Add(self.interval)
  21. }
  22. func (self timer) String() string {
  23. return fmt.Sprintf("Timer(id=%d, callback=%s, deadline=%s, repeats=%v)", self.id, utils.FunctionName(self.callback), time.Until(self.deadline), self.repeats)
  24. }
  25. func (self *Loop) add_timer(interval time.Duration, repeats bool, callback TimerCallback) (IdType, error) {
  26. if self.timers == nil {
  27. return 0, fmt.Errorf("Cannot add timers before starting the run loop, add them in OnInitialize instead")
  28. }
  29. self.timer_id_counter++
  30. t := timer{interval: interval, repeats: repeats, callback: callback, id: self.timer_id_counter}
  31. t.update_deadline(time.Now())
  32. self.timers = append(self.timers, &t)
  33. self.sort_timers()
  34. return t.id, nil
  35. }
  36. func (self *Loop) remove_timer(id IdType) bool {
  37. if self.timers == nil {
  38. return false
  39. }
  40. for i := 0; i < len(self.timers); i++ {
  41. if self.timers[i].id == id {
  42. self.timers = append(self.timers[:i], self.timers[i+1:]...)
  43. return true
  44. }
  45. }
  46. return false
  47. }
  48. func (self *Loop) dispatch_timers(now time.Time) error {
  49. self.timers_temp = self.timers_temp[:0]
  50. self.timers, self.timers_temp = self.timers_temp, self.timers
  51. dispatched := false
  52. for _, t := range self.timers_temp {
  53. if now.After(t.deadline) {
  54. dispatched = true
  55. err := t.callback(t.id)
  56. if err != nil {
  57. return err
  58. }
  59. if t.repeats {
  60. t.update_deadline(now)
  61. self.timers = append(self.timers, t)
  62. }
  63. } else {
  64. self.timers = append(self.timers, t)
  65. }
  66. }
  67. if dispatched {
  68. self.sort_timers() // needed because a timer callback could have added a new timer
  69. }
  70. return nil
  71. }
  72. func (self *Loop) sort_timers() {
  73. slices.SortStableFunc(self.timers, func(a, b *timer) int { return a.deadline.Compare(b.deadline) })
  74. }