@@ -22,6 +22,13 @@ type FakeClock struct {
2222
2323 // counter tracking the number of wakeups (protected by mu)
2424 wakeups int
25+
26+ // counter tracking the number of cancelled sleeps (protected by mu)
27+ sleepAborts int
28+
29+ // counter tracking the number of sleepers who have ever gone to sleep
30+ // (protected by mu)
31+ sleepersAggregate int
2532}
2633
2734// NewFakeClock returns an initialized FakeClock instance.
@@ -75,6 +82,22 @@ func (f *FakeClock) NumSleepers() int {
7582 return len (f .sleepers )
7683}
7784
85+ // NumAggSleepers returns the number of goroutines who have ever slept under
86+ // SleepFor and SleepUntil calls.
87+ func (f * FakeClock ) NumAggSleepers () int {
88+ f .mu .Lock ()
89+ defer f .mu .Unlock ()
90+ return f .sleepersAggregate
91+ }
92+
93+ // NumSleepAborts returns the number of calls to SleepFor and SleepUntil which
94+ // have ended prematurely due to canceled contexts.
95+ func (f * FakeClock ) NumSleepAborts () int {
96+ f .mu .Lock ()
97+ defer f .mu .Unlock ()
98+ return f .sleepAborts
99+ }
100+
78101// Sleepers returns the number of goroutines waiting in SleepFor and SleepUntil
79102// calls.
80103func (f * FakeClock ) Sleepers () []time.Time {
@@ -96,6 +119,26 @@ func (f *FakeClock) AwaitSleepers(n int) {
96119 }
97120}
98121
122+ // AwaitAggSleepers waits until the aggregate number of sleepers exceeds its
123+ // argument
124+ func (f * FakeClock ) AwaitAggSleepers (n int ) {
125+ f .mu .Lock ()
126+ defer f .mu .Unlock ()
127+ for f .sleepersAggregate < n {
128+ f .cond .Wait ()
129+ }
130+ }
131+
132+ // AwaitSleepAborts waits until the number of aborted sleepers exceeds its
133+ // argument
134+ func (f * FakeClock ) AwaitSleepAborts (n int ) {
135+ f .mu .Lock ()
136+ defer f .mu .Unlock ()
137+ for f .sleepAborts < n {
138+ f .cond .Wait ()
139+ }
140+ }
141+
99142// Wakeups returns the number of sleepers that have been awoken (useful for
100143// verifying that nothing was woken up when advancing time)
101144func (f * FakeClock ) Wakeups () int {
@@ -127,24 +170,30 @@ func (f *FakeClock) setAbsoluteWaiter(until time.Time) chan struct{} {
127170 return ch
128171 }
129172 f .sleepers [ch ] = until
173+ f .sleepersAggregate ++
130174
131175 f .cond .Broadcast ()
132176 return ch
133177}
134178
135- func (f * FakeClock ) removeWaiter (ch chan struct {}) {
179+ func (f * FakeClock ) removeWaiter (ch chan struct {}, abort bool ) {
136180 f .mu .Lock ()
137181 defer f .mu .Unlock ()
182+ // If the channel is present, and this was an abort, increment the
183+ // aborts counter.
184+ if _ , ok := f .sleepers [ch ]; ok && abort {
185+ f .sleepAborts ++
186+ }
138187 delete (f .sleepers , ch )
139188 f .cond .Broadcast ()
140189}
141190
142191// SleepUntil blocks until either ctx expires or until arrives.
143192// Return value is false if context-cancellation/expiry prompted an
144193// early return
145- func (f * FakeClock ) SleepUntil (ctx context.Context , until time.Time ) bool {
194+ func (f * FakeClock ) SleepUntil (ctx context.Context , until time.Time ) ( success bool ) {
146195 ch := f .setAbsoluteWaiter (until )
147- defer f .removeWaiter (ch )
196+ defer func () { f .removeWaiter (ch , ! success ) }( )
148197 select {
149198 case <- ch :
150199 return true
@@ -158,17 +207,18 @@ func (f *FakeClock) setRelativeWaiter(dur time.Duration) chan struct{} {
158207 f .mu .Lock ()
159208 defer f .mu .Unlock ()
160209 f .sleepers [ch ] = f .current .Add (dur )
210+ f .sleepersAggregate ++
161211 f .cond .Broadcast ()
162212 return ch
163213}
164214
165215// SleepFor is the relative-time equivalent of SleepUntil.
166- func (f * FakeClock ) SleepFor (ctx context.Context , dur time.Duration ) bool {
216+ func (f * FakeClock ) SleepFor (ctx context.Context , dur time.Duration ) ( success bool ) {
167217 if dur <= 0 {
168218 return true
169219 }
170220 ch := f .setRelativeWaiter (dur )
171- defer f .removeWaiter (ch )
221+ defer func () { f .removeWaiter (ch , ! success ) }( )
172222 select {
173223 case <- ch :
174224 return true
0 commit comments