LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package time | 5 package time |
6 | 6 |
7 import ( | 7 import ( |
8 "os" | 8 "os" |
9 "syscall" | 9 "syscall" |
10 "sync" | 10 "sync" |
11 "container/heap" | 11 "container/heap" |
12 ) | 12 ) |
13 | 13 |
14 // The Timer type represents a single After or AfterFunc event. | 14 // The Timer type represents a single event. |
| 15 // When the Timer expires, the current time will be sent on C |
| 16 // unless the Timer represents an AfterFunc event. |
15 type Timer struct { | 17 type Timer struct { |
| 18 C <-chan int64 |
16 t int64 // The absolute time that the event should fire. | 19 t int64 // The absolute time that the event should fire. |
17 f func(int64) // The function to call when the event fires. | 20 f func(int64) // The function to call when the event fires. |
18 i int // The event's index inside eventHeap. | 21 i int // The event's index inside eventHeap. |
19 } | 22 } |
20 | 23 |
21 type timerHeap []*Timer | 24 type timerHeap []*Timer |
22 | 25 |
23 var timerMutex sync.Mutex | 26 // forever is the absolute time (in ns) of an event that is forever away. |
24 var timers timerHeap | |
25 var currentSleeper int64 | |
26 | |
27 const forever = 1 << 62 | 27 const forever = 1 << 62 |
| 28 |
| 29 // maxSleepTime is the maximum length of time that a sleeper |
| 30 // sleeps for before checking if it is defunct. |
28 const maxSleepTime = 1e9 | 31 const maxSleepTime = 1e9 |
29 | 32 |
| 33 var ( |
| 34 // timerMutex guards the variables inside this var group. |
| 35 timerMutex sync.Mutex |
| 36 |
| 37 // timers holds a binary heap of pending events, terminated with a senti
nel. |
| 38 timers timerHeap |
| 39 |
| 40 // currentSleeper is an ever-incrementing counter which represents |
| 41 // the current sleeper. It allows older sleepers to detect that they are |
| 42 // defunct and exit. |
| 43 currentSleeper int64 |
| 44 ) |
| 45 |
30 func init() { | 46 func init() { |
31 » timers.Push(&Timer{forever, nil, 0}) // sentinel | 47 » timers.Push(&Timer{t: forever}) // sentinel |
32 } | 48 } |
33 | 49 |
34 // Sleep pauses the current goroutine for at least ns nanoseconds. | 50 // Sleep pauses the current goroutine for at least ns nanoseconds. |
35 // Higher resolution sleeping may be provided by syscall.Nanosleep· | 51 // Higher resolution sleeping may be provided by syscall.Nanosleep· |
36 // on some operating systems. | 52 // on some operating systems. |
37 func Sleep(ns int64) os.Error { | 53 func Sleep(ns int64) os.Error { |
38 _, err := sleep(Nanoseconds(), ns) | 54 _, err := sleep(Nanoseconds(), ns) |
39 return err | 55 return err |
40 } | 56 } |
41 | 57 |
42 // sleep takes the current time and a duration, | 58 // sleep takes the current time and a duration, |
43 // pauses for at least ns nanoseconds, and | 59 // pauses for at least ns nanoseconds, and |
44 // returns the current time and an error. | 60 // returns the current time and an error. |
45 func sleep(t, ns int64) (int64, os.Error) { | 61 func sleep(t, ns int64) (int64, os.Error) { |
46 // TODO(cw): use monotonic-time once it's available | 62 // TODO(cw): use monotonic-time once it's available |
47 end := t + ns | 63 end := t + ns |
48 for t < end { | 64 for t < end { |
49 errno := syscall.Sleep(end - t) | 65 errno := syscall.Sleep(end - t) |
50 if errno != 0 && errno != syscall.EINTR { | 66 if errno != 0 && errno != syscall.EINTR { |
51 return 0, os.NewSyscallError("sleep", errno) | 67 return 0, os.NewSyscallError("sleep", errno) |
52 } | 68 } |
53 t = Nanoseconds() | 69 t = Nanoseconds() |
54 } | 70 } |
55 return t, nil | 71 return t, nil |
56 } | 72 } |
57 | 73 |
58 // After waits at least ns nanoseconds before sending the current time | 74 // NewTimer creates a new Timer that will send |
59 // on the returned channel. The returned Timer can be used to | 75 // the current time on its channel after at least ns nanoseconds. |
60 // prevent the send. | 76 func NewTimer(ns int64) *Timer { |
61 func After(ns int64) (<-chan int64, *Timer) { | |
62 c := make(chan int64, 1) | 77 c := make(chan int64, 1) |
63 e := after(ns, func(t int64) { c <- t }) | 78 e := after(ns, func(t int64) { c <- t }) |
64 » return c, e | 79 » e.C = c |
| 80 » return e |
| 81 } |
| 82 |
| 83 // After waits at least ns nanoseconds before sending the current time |
| 84 // on the returned channel. |
| 85 // It is equivalent to NewTimer(ns).C. |
| 86 func After(ns int64) <-chan int64 { |
| 87 » return NewTimer(ns).C |
65 } | 88 } |
66 | 89 |
67 // AfterFunc waits at least ns nanoseconds before calling f | 90 // AfterFunc waits at least ns nanoseconds before calling f |
68 // in its own goroutine. It returns a Timer that can | 91 // in its own goroutine. It returns a Timer that can |
69 // be used to prevent the call. | 92 // be used to cancel the call using its Stop method. |
70 func AfterFunc(ns int64, f func()) *Timer { | 93 func AfterFunc(ns int64, f func()) *Timer { |
71 return after(ns, func(_ int64) { | 94 return after(ns, func(_ int64) { |
72 go f() | 95 go f() |
73 }) | 96 }) |
74 } | 97 } |
75 | 98 |
76 // Stop prevents the Timer from firing. | 99 // Stop prevents the Timer from firing. |
77 // It returns true if it succeeded (i.e. the | 100 // It returns true if the call stops the timer, false if the timer has already |
78 // timer has not already fired or been stopped). | 101 // expired or stopped. |
79 func (e *Timer) Stop() (ok bool) { | 102 func (e *Timer) Stop() (ok bool) { |
80 timerMutex.Lock() | 103 timerMutex.Lock() |
81 // Avoid removing the first event in the queue so that | 104 // Avoid removing the first event in the queue so that |
82 // we don't start a new sleeper unnecessarily. | 105 // we don't start a new sleeper unnecessarily. |
83 if e.i > 0 { | 106 if e.i > 0 { |
84 heap.Remove(timers, e.i) | 107 heap.Remove(timers, e.i) |
85 } | 108 } |
86 ok = e.f != nil | 109 ok = e.f != nil |
87 e.f = nil | 110 e.f = nil |
88 timerMutex.Unlock() | 111 timerMutex.Unlock() |
89 return | 112 return |
90 } | 113 } |
91 | 114 |
92 // after is the implementation of After and AfterFunc. | 115 // after is the implementation of After and AfterFunc. |
93 // When the current time is after ns, it calls f with the current time. | 116 // When the current time is after ns, it calls f with the current time. |
94 // It assumes that f will not block. | 117 // It assumes that f will not block. |
95 func after(ns int64, f func(int64)) (e *Timer) { | 118 func after(ns int64, f func(int64)) (e *Timer) { |
| 119 now := Nanoseconds() |
96 t := Nanoseconds() + ns | 120 t := Nanoseconds() + ns |
97 » if t >= forever { | 121 » if ns > 0 && t < now { |
98 » » return &Timer{} | 122 » » panic("time: time overflow") |
99 } | 123 } |
100 timerMutex.Lock() | 124 timerMutex.Lock() |
101 t0 := timers[0].t | 125 t0 := timers[0].t |
102 » e = &Timer{t, f, -1} | 126 » e = &Timer{nil, t, f, -1} |
103 heap.Push(timers, e) | 127 heap.Push(timers, e) |
104 // Start a new sleeper if the new event is before | 128 // Start a new sleeper if the new event is before |
105 // the first event in the queue. If the length of time | 129 // the first event in the queue. If the length of time |
106 » // until the new event is more than maxSleepTime, | 130 » // until the new event is at least maxSleepTime, |
107 // then we're guaranteed that the sleeper will wake up | 131 // then we're guaranteed that the sleeper will wake up |
108 // in time to service it, so no new sleeper is needed. | 132 // in time to service it, so no new sleeper is needed. |
109 if t0 > t && (t0 == forever || ns < maxSleepTime) { | 133 if t0 > t && (t0 == forever || ns < maxSleepTime) { |
110 currentSleeper++ | 134 currentSleeper++ |
111 go sleeper(currentSleeper) | 135 go sleeper(currentSleeper) |
112 } | 136 } |
113 timerMutex.Unlock() | 137 timerMutex.Unlock() |
114 return | 138 return |
115 } | 139 } |
116 | 140 |
117 // sleeper continually looks at the earliest event in the queue, waits until it
happens, | 141 // sleeper continually looks at the earliest event in the queue, waits until it
happens, |
118 // then removes any events in the queue that are due. It stops when the queue | 142 // then removes any events in the queue that are due. It stops when the queue |
119 // is empty, or when another sleeper has been started. | 143 // is empty or when another sleeper has been started. |
120 //· | |
121 func sleeper(sleeperId int64) { | 144 func sleeper(sleeperId int64) { |
122 timerMutex.Lock() | 145 timerMutex.Lock() |
123 e := timers[0] | 146 e := timers[0] |
124 t := Nanoseconds() | 147 t := Nanoseconds() |
125 for e.t != forever { | 148 for e.t != forever { |
126 » » dt := e.t - t | 149 » » if dt := e.t - t; dt > 0 { |
127 » » if dt > maxSleepTime { | 150 » » » if dt > maxSleepTime { |
128 » » » dt = maxSleepTime | 151 » » » » dt = maxSleepTime |
129 » » } | 152 » » » } |
130 » » timerMutex.Unlock() | 153 » » » timerMutex.Unlock() |
131 » » sleep(t, dt) | 154 » » » syscall.Sleep(dt) |
132 » » timerMutex.Lock() | 155 » » » timerMutex.Lock() |
133 » » if currentSleeper != sleeperId { | 156 » » » if currentSleeper != sleeperId { |
134 » » » // Another sleeper has been started, making this one red
undant. | 157 » » » » // Another sleeper has been started, making this
one redundant. |
135 » » » break | 158 » » » » break |
| 159 » » » } |
136 } | 160 } |
137 e = timers[0] | 161 e = timers[0] |
138 t = Nanoseconds() | 162 t = Nanoseconds() |
139 for t >= e.t { | 163 for t >= e.t { |
140 if e.f != nil { | 164 if e.f != nil { |
141 e.f(t) | 165 e.f(t) |
142 e.f = nil | 166 e.f = nil |
143 } | 167 } |
144 heap.Pop(timers) | 168 heap.Pop(timers) |
145 e = timers[0] | 169 e = timers[0] |
(...skipping 24 matching lines...) Expand all Loading... |
170 | 194 |
171 func (timerHeap) Pop() interface{} { | 195 func (timerHeap) Pop() interface{} { |
172 // TODO: possibly shrink array. | 196 // TODO: possibly shrink array. |
173 n := len(timers) - 1 | 197 n := len(timers) - 1 |
174 e := timers[n] | 198 e := timers[n] |
175 timers[n] = nil | 199 timers[n] = nil |
176 timers = timers[0:n] | 200 timers = timers[0:n] |
177 e.i = -1 | 201 e.i = -1 |
178 return e | 202 return e |
179 } | 203 } |
LEFT | RIGHT |