()
| 91 | } |
| 92 | |
| 93 | func timerRoutine() { |
| 94 | var now time.Time |
| 95 | var last int |
| 96 | |
| 97 | var sleepTimerActive bool |
| 98 | sleepTimer := time.NewTimer(time.Second) |
| 99 | sleepTimer.Stop() |
| 100 | |
| 101 | Loop: |
| 102 | for { |
| 103 | select { |
| 104 | case <-sleepTimer.C: |
| 105 | |
| 106 | case <-rescheduleC: |
| 107 | // If not yet received a value from sleepTimer.C, the timer must be |
| 108 | // stopped and—if Stop reports that the timer expired before being |
| 109 | // stopped—the channel explicitly drained. |
| 110 | if !sleepTimer.Stop() && sleepTimerActive { |
| 111 | <-sleepTimer.C |
| 112 | } |
| 113 | } |
| 114 | sleepTimerActive = false |
| 115 | |
| 116 | Reschedule: |
| 117 | now = time.Now() |
| 118 | |
| 119 | mutex.Lock() |
| 120 | if len(timers) == 0 { |
| 121 | mutex.Unlock() |
| 122 | continue Loop |
| 123 | } |
| 124 | |
| 125 | t := timers[0] |
| 126 | delta := t.when.Sub(now) |
| 127 | |
| 128 | // Sleep if not expired. |
| 129 | if delta > 0 { |
| 130 | mutex.Unlock() |
| 131 | sleepTimer.Reset(delta) |
| 132 | sleepTimerActive = true |
| 133 | continue Loop |
| 134 | } |
| 135 | |
| 136 | // Timer expired. Trigger the timer's function callback. |
| 137 | t.f(&now) |
| 138 | |
| 139 | // Remove from heap. |
| 140 | last = len(timers) - 1 |
| 141 | if last > 0 { |
| 142 | timers[0] = timers[last] |
| 143 | timers[0].i = 0 |
| 144 | } |
| 145 | timers[last] = nil |
| 146 | timers = timers[:last] |
| 147 | if last > 0 { |
| 148 | siftdownTimer(0) |
| 149 | } |
| 150 | t.i = -1 // mark as removed |
no test coverage detected
searching dependent graphs…