Left: | ||
Right: |
OLD | NEW |
---|---|
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" | |
11 "container/heap" | |
10 ) | 12 ) |
11 | 13 |
14 // The event type represents a single After event. | |
15 type event struct { | |
16 t int64 // The absolute time that the event should be fire d. | |
r
2010/12/06 16:20:56
s/be fired/fire/
rog
2010/12/06 17:35:27
Done.
| |
17 c chan<- int64 // The channel to send on. | |
18 sleeping bool // A sleeper is sleeping for this event. | |
19 } | |
20 | |
21 type eventHeap []*event | |
22 | |
23 var events eventHeap | |
24 var eventMutex sync.Mutex | |
25 | |
26 func init() { | |
27 events.Push(&event{1 << 62, nil, true}) // sentinel | |
28 } | |
29 | |
12 // Sleep pauses the current goroutine for at least ns nanoseconds. | 30 // Sleep pauses the current goroutine for at least ns nanoseconds. |
13 // Higher resolution sleeping may be provided by syscall.Nanosleep· | 31 // Higher resolution sleeping may be provided by syscall.Nanosleep· |
14 // on some operating systems. | 32 // on some operating systems. |
15 func Sleep(ns int64) os.Error { | 33 func Sleep(ns int64) os.Error { |
16 _, err := sleep(Nanoseconds(), ns) | 34 _, err := sleep(Nanoseconds(), ns) |
17 return err | 35 return err |
18 } | 36 } |
19 | 37 |
20 // After waits at least ns nanoseconds before sending the current time | |
21 // on the returned channel. | |
22 func After(ns int64) <-chan int64 { | |
23 t := Nanoseconds() | |
24 ch := make(chan int64, 1) | |
25 go func() { | |
26 t, _ = sleep(t, ns) | |
27 ch <- t | |
28 }() | |
29 return ch | |
30 } | |
31 | |
32 // sleep takes the current time and a duration, | 38 // sleep takes the current time and a duration, |
33 // pauses for at least ns nanoseconds, and | 39 // pauses for at least ns nanoseconds, and |
34 // returns the current time and an error. | 40 // returns the current time and an error. |
35 func sleep(t, ns int64) (int64, os.Error) { | 41 func sleep(t, ns int64) (int64, os.Error) { |
36 // TODO(cw): use monotonic-time once it's available | 42 // TODO(cw): use monotonic-time once it's available |
37 end := t + ns | 43 end := t + ns |
38 for t < end { | 44 for t < end { |
39 errno := syscall.Sleep(end - t) | 45 errno := syscall.Sleep(end - t) |
40 if errno != 0 && errno != syscall.EINTR { | 46 if errno != 0 && errno != syscall.EINTR { |
41 return 0, os.NewSyscallError("sleep", errno) | 47 return 0, os.NewSyscallError("sleep", errno) |
42 } | 48 } |
43 t = Nanoseconds() | 49 t = Nanoseconds() |
44 } | 50 } |
45 return t, nil | 51 return t, nil |
46 } | 52 } |
53 | |
54 // After waits at least ns nanoseconds before sending the current time | |
55 // on the returned channel. | |
56 func After(ns int64) <-chan int64 { | |
57 c := make(chan int64, 1) | |
58 t := ns + Nanoseconds() | |
59 eventMutex.Lock() | |
60 t0 := events[0].t | |
61 heap.Push(events, &event{t, c, false}) | |
62 if t < t0 { | |
63 go sleeper() | |
64 } | |
65 eventMutex.Unlock() | |
66 return c | |
67 } | |
68 | |
69 // sleeper continually looks at the earliest event in the queue, marks it | |
70 // as sleeping, waits until it happens, then removes any events | |
71 // in the queue that are due. It stops when it finds an event that is | |
72 // already marked as sleeping. When an event is inserted before the first item, | |
73 // a new sleeper is started. | |
74 // | |
75 // Scheduling vagaries may mean that sleepers may not wake up in | |
r
2010/12/06 16:20:56
s/may // (too many mays)
rog
2010/12/06 17:35:27
Done.
| |
76 // exactly the order of the events that they are waiting for, | |
77 // but this does not matter as long as there are at least as | |
78 // many sleepers as events marked sleeping (invariant). This ensures that | |
79 // there is always a sleeper to service the remaining events. | |
80 // | |
81 // A sleeper will remove at least the event it has been waiting for | |
82 // unless the event has already been removed by another sleeper. Both | |
83 // cases preserve the above invariant. | |
r
2010/12/06 16:20:56
'above' is not an adjective.
Both cases preserve
rog
2010/12/06 17:35:27
Done.
| |
84 func sleeper() { | |
85 eventMutex.Lock() | |
86 e := events[0] | |
87 for !e.sleeping { | |
88 t := Nanoseconds() | |
89 if dt := e.t - t; dt > 0 { | |
90 e.sleeping = true | |
91 eventMutex.Unlock() | |
92 if nt, err := sleep(t, dt); err != nil { | |
93 // If sleep has encountered an error, | |
94 // there's not much we can do. We pretend | |
95 // that time really has advanced by the required | |
96 // amount and lie to the rest of the system. | |
97 t = e.t | |
98 } else { | |
99 t = nt | |
100 } | |
101 eventMutex.Lock() | |
102 e = events[0] | |
103 } | |
104 for t >= e.t { | |
105 e.c <- t | |
106 heap.Pop(events) | |
107 e = events[0] | |
108 } | |
109 } | |
110 eventMutex.Unlock() | |
111 } | |
112 | |
113 func (eventHeap) Len() int { | |
114 return len(events) | |
115 } | |
116 | |
117 func (eventHeap) Less(i, j int) bool { | |
118 return events[i].t < events[j].t | |
119 } | |
120 | |
121 func (eventHeap) Swap(i, j int) { | |
122 events[i], events[j] = events[j], events[i] | |
123 } | |
124 | |
125 func (eventHeap) Push(x interface{}) { | |
126 events = append(events, x.(*event)) | |
127 } | |
128 | |
129 func (eventHeap) Pop() interface{} { | |
130 // TODO: possibly shrink array. | |
131 n := len(events) - 1 | |
132 e := events[n] | |
133 events[n] = nil | |
134 events = events[0:n] | |
135 return e | |
136 } | |
OLD | NEW |