mirror of https://go.googlesource.com/go
92 lines
3.6 KiB
Go
92 lines
3.6 KiB
Go
// 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
|
|
|
|
import "unsafe"
|
|
|
|
// Note: The runtime knows the layout of struct Ticker, since newTimer allocates it.
|
|
// Note also that Ticker and Timer have the same layout, so that newTimer can handle both.
|
|
// The initTimer and initTicker fields are named differently so that
|
|
// users cannot convert between the two without unsafe.
|
|
|
|
// A Ticker holds a channel that delivers “ticks” of a clock
|
|
// at intervals.
|
|
type Ticker struct {
|
|
C <-chan Time // The channel on which the ticks are delivered.
|
|
initTicker bool
|
|
}
|
|
|
|
// NewTicker returns a new [Ticker] containing a channel that will send
|
|
// the current time on the channel after each tick. The period of the
|
|
// ticks is specified by the duration argument. The ticker will adjust
|
|
// the time interval or drop ticks to make up for slow receivers.
|
|
// The duration d must be greater than zero; if not, NewTicker will
|
|
// panic.
|
|
//
|
|
// Before Go 1.23, the garbage collector did not recover
|
|
// tickers that had not yet expired or been stopped, so code often
|
|
// immediately deferred t.Stop after calling NewTicker, to make
|
|
// the ticker recoverable when it was no longer needed.
|
|
// As of Go 1.23, the garbage collector can recover unreferenced
|
|
// tickers, even if they haven't been stopped.
|
|
// The Stop method is no longer necessary to help the garbage collector.
|
|
// (Code may of course still want to call Stop to stop the ticker for other reasons.)
|
|
func NewTicker(d Duration) *Ticker {
|
|
if d <= 0 {
|
|
panic("non-positive interval for NewTicker")
|
|
}
|
|
// Give the channel a 1-element time buffer.
|
|
// If the client falls behind while reading, we drop ticks
|
|
// on the floor until the client catches up.
|
|
c := make(chan Time, 1)
|
|
t := (*Ticker)(unsafe.Pointer(newTimer(when(d), int64(d), sendTime, c, syncTimer(c))))
|
|
t.C = c
|
|
return t
|
|
}
|
|
|
|
// Stop turns off a ticker. After Stop, no more ticks will be sent.
|
|
// Stop does not close the channel, to prevent a concurrent goroutine
|
|
// reading from the channel from seeing an erroneous "tick".
|
|
func (t *Ticker) Stop() {
|
|
if !t.initTicker {
|
|
// This is misuse, and the same for time.Timer would panic,
|
|
// but this didn't always panic, and we keep it not panicking
|
|
// to avoid breaking old programs. See issue 21874.
|
|
return
|
|
}
|
|
stopTimer((*Timer)(unsafe.Pointer(t)))
|
|
}
|
|
|
|
// Reset stops a ticker and resets its period to the specified duration.
|
|
// The next tick will arrive after the new period elapses. The duration d
|
|
// must be greater than zero; if not, Reset will panic.
|
|
func (t *Ticker) Reset(d Duration) {
|
|
if d <= 0 {
|
|
panic("non-positive interval for Ticker.Reset")
|
|
}
|
|
if !t.initTicker {
|
|
panic("time: Reset called on uninitialized Ticker")
|
|
}
|
|
resetTimer((*Timer)(unsafe.Pointer(t)), when(d), int64(d))
|
|
}
|
|
|
|
// Tick is a convenience wrapper for [NewTicker] providing access to the ticking
|
|
// channel only. Unlike NewTicker, Tick will return nil if d <= 0.
|
|
//
|
|
// Before Go 1.23, this documentation warned that the underlying
|
|
// [Ticker] would never be recovered by the garbage collector, and that
|
|
// if efficiency was a concern, code should use NewTicker instead and
|
|
// call [Ticker.Stop] when the ticker is no longer needed.
|
|
// As of Go 1.23, the garbage collector can recover unreferenced
|
|
// tickers, even if they haven't been stopped.
|
|
// The Stop method is no longer necessary to help the garbage collector.
|
|
// There is no longer any reason to prefer NewTicker when Tick will do.
|
|
func Tick(d Duration) <-chan Time {
|
|
if d <= 0 {
|
|
return nil
|
|
}
|
|
return NewTicker(d).C
|
|
}
|