Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: common/clock/systemtimer.go

Issue 1679023005: Add Context cancellation to clock. (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: More test coverage, cleanup, consolidation. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package clock 5 package clock
6 6
7 import ( 7 import (
8 "time" 8 "time"
9
10 "golang.org/x/net/context"
9 ) 11 )
10 12
11 type systemTimer struct { 13 type systemTimer struct {
12 » T *time.Timer // The underlying timer. Starts as nil, is initialized on Reset. 14 » // base is the underlying timer. It starts as nil, and is initialized on
15 » // Reset.
16 » ctx context.Context
iannucci 2016/02/10 22:30:28 base? ctx?
dnj (Google) 2016/02/11 01:26:54 Done.
17
18 » // timerC is the current timer channel.
19 » timerC chan TimerResult
20 » // timerDoneC is a signal channel to alert our monitor that this timer h as
21 » // been canceled.
22 » timerStoppedC chan struct{}
iannucci 2016/02/10 22:30:28 comments
dnj (Google) 2016/02/11 01:26:54 Done.
23 » // timerMonitorResultC returns true if the timer monitor was prematurely
24 » // terminated, false if not.
25 » timerMonitorResultC chan bool
13 } 26 }
14 27
15 var _ Timer = (*systemTimer)(nil) 28 var _ Timer = (*systemTimer)(nil)
16 29
17 func (t *systemTimer) GetC() <-chan time.Time { 30 func (t *systemTimer) GetC() <-chan TimerResult {
18 » if t.T == nil { 31 » return t.timerC
19 » » return nil
20 » }
21 » return t.T.C
22 } 32 }
23 33
24 func (t *systemTimer) Reset(d time.Duration) bool { 34 func (t *systemTimer) Reset(d time.Duration) (running bool) {
25 » if t.T == nil { 35 » running = t.Stop()
26 » » t.T = time.NewTimer(d) 36 » t.reset()
27 » » return false 37
38 » // If our Context is already done, finish immediately.
39 » select {
iannucci 2016/02/10 22:30:28 I'd use t.ctx.Err() instead
dnj (Google) 2016/02/11 01:26:54 Done.
40 » case <-t.ctx.Done():
41 » » t.timerC <- TimerResult{Time: time.Now(), Err: t.ctx.Err()}
42 » » return
43 » default:
44 » » break
28 } 45 }
29 » return t.T.Reset(d) 46
47 » // Start a monitor goroutine and our actual timer. Copy our channels, si nce
48 » // future stop/reset will change the systemTimer's values and our gorout ine
49 » // should only operate on this round's values.
50 » timerC := t.timerC
51 » timerStoppedC := make(chan struct{})
52 » timerMonitorResultC := make(chan bool, 1)
53 » go func() {
54 » » interrupted := false
55 » » defer func() {
56 » » » timerMonitorResultC <- interrupted
57 » » }()
58
59 » » select {
60 » » case <-timerStoppedC:
61 » » » interrupted = true
62
63 » » case <-t.ctx.Done():
64 » » » timerC <- TimerResult{Time: time.Now(), Err: t.ctx.Err() }
65 » » case now := <-time.After(d):
66 » » » // For determinism, prioritize Context cancellation over timer expiration.
67 » » » select {
68 » » » case <-t.ctx.Done():
69 » » » » timerC <- TimerResult{Time: now, Err: t.ctx.Err( )}
70 » » » default:
71 » » » » break
72 » » » }
iannucci 2016/02/10 22:30:28 also Err()
dnj (Google) 2016/02/11 01:26:54 Done.
73
74 » » » timerC <- TimerResult{Time: now}
75 » » }
76 » }()
77
78 » t.timerStoppedC = timerStoppedC
79 » t.timerMonitorResultC = timerMonitorResultC
80 » return
30 } 81 }
31 82
32 func (t *systemTimer) Stop() bool { 83 func (t *systemTimer) Stop() bool {
33 » if t.T == nil { 84 » if t.timerStoppedC == nil {
34 return false 85 return false
35 } 86 }
36 » return t.T.Stop() 87 » close(t.timerStoppedC)
88 » t.timerStoppedC = nil
89 » return <-t.timerMonitorResultC
37 } 90 }
91
92 func (t *systemTimer) reset() {
iannucci 2016/02/10 22:30:28 let's inline this
dnj (Google) 2016/02/11 01:26:54 Done.
93 t.timerC = make(chan TimerResult, 1)
94 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698