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 5package time 6 7// Sleep pauses the current goroutine for at least the duration d. 8// A negative or zero duration causes Sleep to return immediately. 9func Sleep(d Duration) 10 11// Interface to timers implemented in package runtime. 12// Must be in sync with ../runtime/time.go:/^type timer 13type runtimeTimer struct { 14 tb uintptr 15 i int 16 17 when int64 18 period int64 19 f func(interface{}, uintptr) // NOTE: must not be closure 20 arg interface{} 21 seq uintptr 22} 23 24// when is a helper function for setting the 'when' field of a runtimeTimer. 25// It returns what the time will be, in nanoseconds, Duration d in the future. 26// If d is negative, it is ignored. If the returned value would be less than 27// zero because of an overflow, MaxInt64 is returned. 28func when(d Duration) int64 { 29 if d <= 0 { 30 return runtimeNano() 31 } 32 t := runtimeNano() + int64(d) 33 if t < 0 { 34 t = 1<<63 - 1 // math.MaxInt64 35 } 36 return t 37} 38 39func startTimer(*runtimeTimer) 40func stopTimer(*runtimeTimer) bool 41 42// The Timer type represents a single event. 43// When the Timer expires, the current time will be sent on C, 44// unless the Timer was created by AfterFunc. 45// A Timer must be created with NewTimer or AfterFunc. 46type Timer struct { 47 C <-chan Time 48 r runtimeTimer 49} 50 51// Stop prevents the Timer from firing. 52// It returns true if the call stops the timer, false if the timer has already 53// expired or been stopped. 54// Stop does not close the channel, to prevent a read from the channel succeeding 55// incorrectly. 56// 57// To prevent a timer created with NewTimer from firing after a call to Stop, 58// check the return value and drain the channel. 59// For example, assuming the program has not received from t.C already: 60// 61// if !t.Stop() { 62// <-t.C 63// } 64// 65// This cannot be done concurrent to other receives from the Timer's 66// channel. 67// 68// For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer 69// has already expired and the function f has been started in its own goroutine; 70// Stop does not wait for f to complete before returning. 71// If the caller needs to know whether f is completed, it must coordinate 72// with f explicitly. 73func (t *Timer) Stop() bool { 74 if t.r.f == nil { 75 panic("time: Stop called on uninitialized Timer") 76 } 77 return stopTimer(&t.r) 78} 79 80// NewTimer creates a new Timer that will send 81// the current time on its channel after at least duration d. 82func NewTimer(d Duration) *Timer { 83 c := make(chan Time, 1) 84 t := &Timer{ 85 C: c, 86 r: runtimeTimer{ 87 when: when(d), 88 f: sendTime, 89 arg: c, 90 }, 91 } 92 startTimer(&t.r) 93 return t 94} 95 96// Reset changes the timer to expire after duration d. 97// It returns true if the timer had been active, false if the timer had 98// expired or been stopped. 99// 100// Resetting a timer must take care not to race with the send into t.C 101// that happens when the current timer expires. 102// If a program has already received a value from t.C, the timer is known 103// to have expired, and t.Reset can be used directly. 104// If a program has not yet received a value from t.C, however, 105// the timer must be stopped and—if Stop reports that the timer expired 106// before being stopped—the channel explicitly drained: 107// 108// if !t.Stop() { 109// <-t.C 110// } 111// t.Reset(d) 112// 113// This should not be done concurrent to other receives from the Timer's 114// channel. 115// 116// Note that it is not possible to use Reset's return value correctly, as there 117// is a race condition between draining the channel and the new timer expiring. 118// Reset should always be invoked on stopped or expired channels, as described above. 119// The return value exists to preserve compatibility with existing programs. 120func (t *Timer) Reset(d Duration) bool { 121 if t.r.f == nil { 122 panic("time: Reset called on uninitialized Timer") 123 } 124 w := when(d) 125 active := stopTimer(&t.r) 126 t.r.when = w 127 startTimer(&t.r) 128 return active 129} 130 131func sendTime(c interface{}, seq uintptr) { 132 // Non-blocking send of time on c. 133 // Used in NewTimer, it cannot block anyway (buffer). 134 // Used in NewTicker, dropping sends on the floor is 135 // the desired behavior when the reader gets behind, 136 // because the sends are periodic. 137 select { 138 case c.(chan Time) <- Now(): 139 default: 140 } 141} 142 143// After waits for the duration to elapse and then sends the current time 144// on the returned channel. 145// It is equivalent to NewTimer(d).C. 146// The underlying Timer is not recovered by the garbage collector 147// until the timer fires. If efficiency is a concern, use NewTimer 148// instead and call Timer.Stop if the timer is no longer needed. 149func After(d Duration) <-chan Time { 150 return NewTimer(d).C 151} 152 153// AfterFunc waits for the duration to elapse and then calls f 154// in its own goroutine. It returns a Timer that can 155// be used to cancel the call using its Stop method. 156func AfterFunc(d Duration, f func()) *Timer { 157 t := &Timer{ 158 r: runtimeTimer{ 159 when: when(d), 160 f: goFunc, 161 arg: f, 162 }, 163 } 164 startTimer(&t.r) 165 return t 166} 167 168func goFunc(arg interface{}, seq uintptr) { 169 go arg.(func())() 170} 171