3538775adfb28c9dc0864182308a13296d1a9b28
[platform/upstream/gcc.git] / libgo / go / time / sleep.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package time
6
7 import (
8         "os"
9         "syscall"
10         "sync"
11         "container/heap"
12 )
13
14 // The event type represents a single After or AfterFunc event.
15 type event struct {
16         t        int64       // The absolute time that the event should fire.
17         f        func(int64) // The function to call when the event fires.
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
30 // Sleep pauses the current goroutine for at least ns nanoseconds.
31 // Higher resolution sleeping may be provided by syscall.Nanosleep 
32 // on some operating systems.
33 func Sleep(ns int64) os.Error {
34         _, err := sleep(Nanoseconds(), ns)
35         return err
36 }
37
38 // sleep takes the current time and a duration,
39 // pauses for at least ns nanoseconds, and
40 // returns the current time and an error.
41 func sleep(t, ns int64) (int64, os.Error) {
42         // TODO(cw): use monotonic-time once it's available
43         end := t + ns
44         for t < end {
45                 errno := syscall.Sleep(end - t)
46                 if errno != 0 && errno != syscall.EINTR {
47                         return 0, os.NewSyscallError("sleep", errno)
48                 }
49                 t = Nanoseconds()
50         }
51         return t, nil
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         after(ns, func(t int64) { c <- t })
59         return c
60 }
61
62 // AfterFunc waits at least ns nanoseconds before calling f
63 // in its own goroutine.
64 func AfterFunc(ns int64, f func()) {
65         after(ns, func(_ int64) {
66                 go f()
67         })
68 }
69
70 // after is the implementation of After and AfterFunc.
71 // When the current time is after ns, it calls f with the current time.
72 // It assumes that f will not block.
73 func after(ns int64, f func(int64)) {
74         t := Nanoseconds() + ns
75         eventMutex.Lock()
76         t0 := events[0].t
77         heap.Push(events, &event{t, f, false})
78         if t < t0 {
79                 go sleeper()
80         }
81         eventMutex.Unlock()
82 }
83
84 // sleeper continually looks at the earliest event in the queue, marks it
85 // as sleeping, waits until it happens, then removes any events
86 // in the queue that are due. It stops when it finds an event that is
87 // already marked as sleeping. When an event is inserted before the first item,
88 // a new sleeper is started.
89 //
90 // Scheduling vagaries mean that sleepers may not wake up in
91 // exactly the order of the events that they are waiting for,
92 // but this does not matter as long as there are at least as
93 // many sleepers as events marked sleeping (invariant). This ensures that
94 // there is always a sleeper to service the remaining events.
95 //
96 // A sleeper will remove at least the event it has been waiting for
97 // unless the event has already been removed by another sleeper.  Both
98 // cases preserve the invariant described above.
99 func sleeper() {
100         eventMutex.Lock()
101         e := events[0]
102         for !e.sleeping {
103                 t := Nanoseconds()
104                 if dt := e.t - t; dt > 0 {
105                         e.sleeping = true
106                         eventMutex.Unlock()
107                         if nt, err := sleep(t, dt); err != nil {
108                                 // If sleep has encountered an error,
109                                 // there's not much we can do. We pretend
110                                 // that time really has advanced by the required
111                                 // amount and lie to the rest of the system.
112                                 t = e.t
113                         } else {
114                                 t = nt
115                         }
116                         eventMutex.Lock()
117                         e = events[0]
118                 }
119                 for t >= e.t {
120                         e.f(t)
121                         heap.Pop(events)
122                         e = events[0]
123                 }
124         }
125         eventMutex.Unlock()
126 }
127
128 func (eventHeap) Len() int {
129         return len(events)
130 }
131
132 func (eventHeap) Less(i, j int) bool {
133         return events[i].t < events[j].t
134 }
135
136 func (eventHeap) Swap(i, j int) {
137         events[i], events[j] = events[j], events[i]
138 }
139
140 func (eventHeap) Push(x interface{}) {
141         events = append(events, x.(*event))
142 }
143
144 func (eventHeap) Pop() interface{} {
145         // TODO: possibly shrink array.
146         n := len(events) - 1
147         e := events[n]
148         events[n] = nil
149         events = events[0:n]
150         return e
151 }