Skip to content

Commit 6e5652b

Browse files
changkunianlancetaylor
authored andcommitted
time: add Ticker.Reset
This CL implements Ticker.Reset method in time package. Benchmark: name time/op TickerReset-12 6.41µs ±10% TickerResetNaive-12 95.7µs ±12% Fixes #33184 Change-Id: I12c651f81e452541bcbbc748b45f038aae1f8dae Reviewed-on: https://go-review.googlesource.com/c/go/+/217362 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent ebe49b2 commit 6e5652b

File tree

6 files changed

+55
-3
lines changed

6 files changed

+55
-3
lines changed

Diff for: api/next.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pkg testing, method (*T) Deadline() (time.Time, bool)
2+
pkg time, method (*Ticker) Reset(Duration)

Diff for: doc/go1.15.html

+10
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,13 @@ <h3 id="minor_library_changes">Minor changes to the library</h3>
8080
<p>
8181
TODO
8282
</p>
83+
84+
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
85+
<dd>
86+
<p><!-- golang.org/issue/33184 -->
87+
The new method
88+
<a href="/pkg/time#Ticker.Reset"><code>Ticker.Reset</code></a>
89+
supports changing the duration of a ticker.
90+
</p>
91+
</dd>
92+
</dl><!-- time -->

Diff for: src/runtime/time.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ func resetTimer(t *timer, when int64) {
233233
resettimer(t, when)
234234
}
235235

236+
// modTimer modifies an existing timer.
237+
//go:linkname modTimer time.modTimer
238+
func modTimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
239+
modtimer(t, when, period, f, arg, seq)
240+
}
241+
236242
// Go runtime.
237243

238244
// Ready the goroutine arg.
@@ -402,7 +408,7 @@ func dodeltimer0(pp *p) bool {
402408
}
403409

404410
// modtimer modifies an existing timer.
405-
// This is called by the netpoll code.
411+
// This is called by the netpoll code or time.Ticker.Reset.
406412
func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
407413
if when < 0 {
408414
when = maxWhen

Diff for: src/time/sleep.go

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ func when(d Duration) int64 {
3939
func startTimer(*runtimeTimer)
4040
func stopTimer(*runtimeTimer) bool
4141
func resetTimer(*runtimeTimer, int64)
42+
func modTimer(t *runtimeTimer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr)
4243

4344
// The Timer type represents a single event.
4445
// When the Timer expires, the current time will be sent on C,

Diff for: src/time/tick.go

+9
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ func (t *Ticker) Stop() {
4646
stopTimer(&t.r)
4747
}
4848

49+
// Reset stops a ticker and resets its period to the specified duration.
50+
// The next tick will arrive after the new period elapses.
51+
func (t *Ticker) Reset(d Duration) {
52+
if t.r.f == nil {
53+
panic("time: Reset called on uninitialized Ticker")
54+
}
55+
modTimer(&t.r, when(d), int64(d), t.r.f, t.r.arg, t.r.seq)
56+
}
57+
4958
// Tick is a convenience wrapper for NewTicker providing access to the ticking
5059
// channel only. While Tick is useful for clients that have no need to shut down
5160
// the Ticker, be aware that without a way to shut it down the underlying

Diff for: src/time/tick_test.go

+27-2
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,17 @@ func TestTicker(t *testing.T) {
3636
for i := 0; i < 5; i++ {
3737
ticker := NewTicker(delta)
3838
t0 := Now()
39-
for i := 0; i < count; i++ {
39+
for i := 0; i < count/2; i++ {
40+
<-ticker.C
41+
}
42+
ticker.Reset(delta * 2)
43+
for i := count / 2; i < count; i++ {
4044
<-ticker.C
4145
}
4246
ticker.Stop()
4347
t1 := Now()
4448
dt := t1.Sub(t0)
45-
target := delta * Duration(count)
49+
target := 3 * delta * Duration(count/2)
4650
slop := target * 2 / 10
4751
if dt < target-slop || dt > target+slop {
4852
errs = append(errs, fmt.Sprintf("%d %s ticks took %s, expected [%s,%s]", count, delta, dt, target-slop, target+slop))
@@ -118,3 +122,24 @@ func BenchmarkTicker(b *testing.B) {
118122
ticker.Stop()
119123
})
120124
}
125+
126+
func BenchmarkTickerReset(b *testing.B) {
127+
benchmark(b, func(n int) {
128+
ticker := NewTicker(Nanosecond)
129+
for i := 0; i < n; i++ {
130+
ticker.Reset(Nanosecond * 2)
131+
}
132+
ticker.Stop()
133+
})
134+
}
135+
136+
func BenchmarkTickerResetNaive(b *testing.B) {
137+
benchmark(b, func(n int) {
138+
ticker := NewTicker(Nanosecond)
139+
for i := 0; i < n; i++ {
140+
ticker.Stop()
141+
ticker = NewTicker(Nanosecond * 2)
142+
}
143+
ticker.Stop()
144+
})
145+
}

0 commit comments

Comments
 (0)