Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(655)

Side by Side Diff: src/pkg/time/sleep.go

Issue 3416043: code review 3416043: time: make After use fewer goroutines and host processes. (Closed)
Patch Set: code review 3416043: time: make After use fewer goroutines and host processes. Created 14 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/pkg/time/sleep_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/time/sleep_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b