timer.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package mint
  2. import (
  3. "time"
  4. )
  5. // This is a simple timer implementation. Timers are stored in a sorted
  6. // list.
  7. // TODO(ekr@rtfm.com): Add a way to uncouple these from the system
  8. // clock.
  9. type timerCb func() error
  10. type timer struct {
  11. label string
  12. cb timerCb
  13. deadline time.Time
  14. duration uint32
  15. }
  16. type timerSet struct {
  17. ts []*timer
  18. }
  19. func newTimerSet() *timerSet {
  20. return &timerSet{}
  21. }
  22. func (ts *timerSet) start(label string, cb timerCb, delayMs uint32) *timer {
  23. now := time.Now()
  24. t := timer{
  25. label,
  26. cb,
  27. now.Add(time.Millisecond * time.Duration(delayMs)),
  28. delayMs,
  29. }
  30. logf(logTypeHandshake, "Timer %s set [%v -> %v]", t.label, now, t.deadline)
  31. var i int
  32. ntimers := len(ts.ts)
  33. for i = 0; i < ntimers; i++ {
  34. if t.deadline.Before(ts.ts[i].deadline) {
  35. break
  36. }
  37. }
  38. tmp := make([]*timer, 0, ntimers+1)
  39. tmp = append(tmp, ts.ts[:i]...)
  40. tmp = append(tmp, &t)
  41. tmp = append(tmp, ts.ts[i:]...)
  42. ts.ts = tmp
  43. return &t
  44. }
  45. // TODO(ekr@rtfm.com): optimize this now that the list is sorted.
  46. // We should be able to do just one list manipulation, as long
  47. // as we're careful about how we handle inserts during callbacks.
  48. func (ts *timerSet) check(now time.Time) error {
  49. for i, t := range ts.ts {
  50. if now.After(t.deadline) {
  51. ts.ts = append(ts.ts[:i], ts.ts[:i+1]...)
  52. if t.cb != nil {
  53. logf(logTypeHandshake, "Timer %s expired [%v > %v]", t.label, now, t.deadline)
  54. cb := t.cb
  55. t.cb = nil
  56. err := cb()
  57. if err != nil {
  58. return err
  59. }
  60. }
  61. } else {
  62. break
  63. }
  64. }
  65. return nil
  66. }
  67. // Returns the next time any of the timers would fire.
  68. func (ts *timerSet) remaining() (bool, time.Duration) {
  69. for _, t := range ts.ts {
  70. if t.cb != nil {
  71. return true, time.Until(t.deadline)
  72. }
  73. }
  74. return false, time.Duration(0)
  75. }
  76. func (ts *timerSet) cancel(label string) {
  77. for _, t := range ts.ts {
  78. if t.label == label {
  79. t.cancel()
  80. }
  81. }
  82. }
  83. func (ts *timerSet) getTimer(label string) *timer {
  84. for _, t := range ts.ts {
  85. if t.label == label && t.cb != nil {
  86. return t
  87. }
  88. }
  89. return nil
  90. }
  91. func (ts *timerSet) getAllTimers() []string {
  92. var ret []string
  93. for _, t := range ts.ts {
  94. if t.cb != nil {
  95. ret = append(ret, t.label)
  96. }
  97. }
  98. return ret
  99. }
  100. func (t *timer) cancel() {
  101. logf(logTypeHandshake, "Timer %s cancelled", t.label)
  102. t.cb = nil
  103. t.label = ""
  104. }