|  | // Copyright 2009 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package time | 
|  |  | 
|  | // Sleep pauses the current goroutine for at least the duration d. | 
|  | // A negative or zero duration causes Sleep to return immediately. | 
|  | func Sleep(d Duration) | 
|  |  | 
|  | // Interface to timers implemented in package runtime. | 
|  | // Must be in sync with ../runtime/time.go:/^type timer | 
|  | type runtimeTimer struct { | 
|  | pp       uintptr | 
|  | when     int64 | 
|  | period   int64 | 
|  | f        func(any, uintptr) // NOTE: must not be closure | 
|  | arg      any | 
|  | seq      uintptr | 
|  | nextwhen int64 | 
|  | status   uint32 | 
|  | } | 
|  |  | 
|  | // when is a helper function for setting the 'when' field of a runtimeTimer. | 
|  | // It returns what the time will be, in nanoseconds, Duration d in the future. | 
|  | // If d is negative, it is ignored. If the returned value would be less than | 
|  | // zero because of an overflow, MaxInt64 is returned. | 
|  | func when(d Duration) int64 { | 
|  | if d <= 0 { | 
|  | return runtimeNano() | 
|  | } | 
|  | t := runtimeNano() + int64(d) | 
|  | if t < 0 { | 
|  | // N.B. runtimeNano() and d are always positive, so addition | 
|  | // (including overflow) will never result in t == 0. | 
|  | t = 1<<63 - 1 // math.MaxInt64 | 
|  | } | 
|  | return t | 
|  | } | 
|  |  | 
|  | func startTimer(*runtimeTimer) | 
|  | func stopTimer(*runtimeTimer) bool | 
|  | func resetTimer(*runtimeTimer, int64) bool | 
|  | func modTimer(t *runtimeTimer, when, period int64, f func(any, uintptr), arg any, seq uintptr) | 
|  |  | 
|  | // The Timer type represents a single event. | 
|  | // When the Timer expires, the current time will be sent on C, | 
|  | // unless the Timer was created by AfterFunc. | 
|  | // A Timer must be created with NewTimer or AfterFunc. | 
|  | type Timer struct { | 
|  | C <-chan Time | 
|  | r runtimeTimer | 
|  | } | 
|  |  | 
|  | // Stop prevents the Timer from firing. | 
|  | // It returns true if the call stops the timer, false if the timer has already | 
|  | // expired or been stopped. | 
|  | // Stop does not close the channel, to prevent a read from the channel succeeding | 
|  | // incorrectly. | 
|  | // | 
|  | // To ensure the channel is empty after a call to Stop, check the | 
|  | // return value and drain the channel. | 
|  | // For example, assuming the program has not received from t.C already: | 
|  | // | 
|  | //	if !t.Stop() { | 
|  | //		<-t.C | 
|  | //	} | 
|  | // | 
|  | // This cannot be done concurrent to other receives from the Timer's | 
|  | // channel or other calls to the Timer's Stop method. | 
|  | // | 
|  | // For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer | 
|  | // has already expired and the function f has been started in its own goroutine; | 
|  | // Stop does not wait for f to complete before returning. | 
|  | // If the caller needs to know whether f is completed, it must coordinate | 
|  | // with f explicitly. | 
|  | func (t *Timer) Stop() bool { | 
|  | if t.r.f == nil { | 
|  | panic("time: Stop called on uninitialized Timer") | 
|  | } | 
|  | return stopTimer(&t.r) | 
|  | } | 
|  |  | 
|  | // NewTimer creates a new Timer that will send | 
|  | // the current time on its channel after at least duration d. | 
|  | func NewTimer(d Duration) *Timer { | 
|  | c := make(chan Time, 1) | 
|  | t := &Timer{ | 
|  | C: c, | 
|  | r: runtimeTimer{ | 
|  | when: when(d), | 
|  | f:    sendTime, | 
|  | arg:  c, | 
|  | }, | 
|  | } | 
|  | startTimer(&t.r) | 
|  | return t | 
|  | } | 
|  |  | 
|  | // Reset changes the timer to expire after duration d. | 
|  | // It returns true if the timer had been active, false if the timer had | 
|  | // expired or been stopped. | 
|  | // | 
|  | // For a Timer created with NewTimer, Reset should be invoked only on | 
|  | // stopped or expired timers with drained channels. | 
|  | // | 
|  | // If a program has already received a value from t.C, the timer is known | 
|  | // to have expired and the channel drained, so t.Reset can be used directly. | 
|  | // If a program has not yet received a value from t.C, however, | 
|  | // the timer must be stopped and—if Stop reports that the timer expired | 
|  | // before being stopped—the channel explicitly drained: | 
|  | // | 
|  | //	if !t.Stop() { | 
|  | //		<-t.C | 
|  | //	} | 
|  | //	t.Reset(d) | 
|  | // | 
|  | // This should not be done concurrent to other receives from the Timer's | 
|  | // channel. | 
|  | // | 
|  | // Note that it is not possible to use Reset's return value correctly, as there | 
|  | // is a race condition between draining the channel and the new timer expiring. | 
|  | // Reset should always be invoked on stopped or expired channels, as described above. | 
|  | // The return value exists to preserve compatibility with existing programs. | 
|  | // | 
|  | // For a Timer created with AfterFunc(d, f), Reset either reschedules | 
|  | // when f will run, in which case Reset returns true, or schedules f | 
|  | // to run again, in which case it returns false. | 
|  | // When Reset returns false, Reset neither waits for the prior f to | 
|  | // complete before returning nor does it guarantee that the subsequent | 
|  | // goroutine running f does not run concurrently with the prior | 
|  | // one. If the caller needs to know whether the prior execution of | 
|  | // f is completed, it must coordinate with f explicitly. | 
|  | func (t *Timer) Reset(d Duration) bool { | 
|  | if t.r.f == nil { | 
|  | panic("time: Reset called on uninitialized Timer") | 
|  | } | 
|  | w := when(d) | 
|  | return resetTimer(&t.r, w) | 
|  | } | 
|  |  | 
|  | // sendTime does a non-blocking send of the current time on c. | 
|  | func sendTime(c any, seq uintptr) { | 
|  | select { | 
|  | case c.(chan Time) <- Now(): | 
|  | default: | 
|  | } | 
|  | } | 
|  |  | 
|  | // After waits for the duration to elapse and then sends the current time | 
|  | // on the returned channel. | 
|  | // It is equivalent to NewTimer(d).C. | 
|  | // The underlying Timer is not recovered by the garbage collector | 
|  | // until the timer fires. If efficiency is a concern, use NewTimer | 
|  | // instead and call Timer.Stop if the timer is no longer needed. | 
|  | func After(d Duration) <-chan Time { | 
|  | return NewTimer(d).C | 
|  | } | 
|  |  | 
|  | // AfterFunc waits for the duration to elapse and then calls f | 
|  | // in its own goroutine. It returns a Timer that can | 
|  | // be used to cancel the call using its Stop method. | 
|  | func AfterFunc(d Duration, f func()) *Timer { | 
|  | t := &Timer{ | 
|  | r: runtimeTimer{ | 
|  | when: when(d), | 
|  | f:    goFunc, | 
|  | arg:  f, | 
|  | }, | 
|  | } | 
|  | startTimer(&t.r) | 
|  | return t | 
|  | } | 
|  |  | 
|  | func goFunc(arg any, seq uintptr) { | 
|  | go arg.(func())() | 
|  | } |