Add progresses time by the given duration. Other operations waiting for the time to advance will be resolved if they are within range. Side effects of operations waiting for the time to advance will take effect on a best-effort basis. Avoid racing with operations that have side effects. Panics if
(d time.Duration)
| 111 | // |
| 112 | // Panics if the duration is negative. |
| 113 | func (c *MockClock) Add(d time.Duration) { |
| 114 | if d < 0 { |
| 115 | panic("cannot add negative duration") |
| 116 | } |
| 117 | |
| 118 | c.mu.Lock() |
| 119 | defer c.mu.Unlock() |
| 120 | |
| 121 | sort.Slice(c.waiters, func(i, j int) bool { |
| 122 | return c.waiters[i].until.Before(c.waiters[j].until) |
| 123 | }) |
| 124 | |
| 125 | newTime := c.now.Add(d) |
| 126 | // newTime won't be recorded until the end of this method. |
| 127 | // This ensures that any waiters that are resolved |
| 128 | // are resolved at the time they were expecting. |
| 129 | |
| 130 | for len(c.waiters) > 0 { |
| 131 | w := c.waiters[0] |
| 132 | if w.until.After(newTime) { |
| 133 | break |
| 134 | } |
| 135 | c.waiters[0] = waiter{} // avoid memory leak |
| 136 | c.waiters = c.waiters[1:] |
| 137 | |
| 138 | // The waiter is within range. |
| 139 | // Travel to the time of the waiter and resolve it. |
| 140 | c.now = w.until |
| 141 | |
| 142 | // The waiter may schedule more work |
| 143 | // so we must release the lock. |
| 144 | c.mu.Unlock() |
| 145 | w.fn() |
| 146 | // Sleeping here is necessary to let the side effects of waiters |
| 147 | // take effect before we continue. |
| 148 | time.Sleep(1 * time.Millisecond) |
| 149 | c.mu.Lock() |
| 150 | } |
| 151 | |
| 152 | c.now = newTime |
| 153 | } |