"container/heap"
)
-// The event type represents a single After event.
+// The event type represents a single After or AfterFunc event.
type event struct {
- t int64 // The absolute time that the event should fire.
- c chan<- int64 // The channel to send on.
- sleeping bool // A sleeper is sleeping for this event.
+ t int64 // The absolute time that the event should fire.
+ f func(int64) // The function to call when the event fires.
+ sleeping bool // A sleeper is sleeping for this event.
}
type eventHeap []*event
// on the returned channel.
func After(ns int64) <-chan int64 {
c := make(chan int64, 1)
- t := ns + Nanoseconds()
+ after(ns, func(t int64) { c <- t })
+ return c
+}
+
+// AfterFunc waits at least ns nanoseconds before calling f
+// in its own goroutine.
+func AfterFunc(ns int64, f func()) {
+ after(ns, func(_ int64) {
+ go f()
+ })
+}
+
+// after is the implementation of After and AfterFunc.
+// When the current time is after ns, it calls f with the current time.
+// It assumes that f will not block.
+func after(ns int64, f func(int64)) {
+ t := Nanoseconds() + ns
eventMutex.Lock()
t0 := events[0].t
- heap.Push(events, &event{t, c, false})
+ heap.Push(events, &event{t, f, false})
if t < t0 {
go sleeper()
}
eventMutex.Unlock()
- return c
}
// sleeper continually looks at the earliest event in the queue, marks it
e = events[0]
}
for t >= e.t {
- e.c <- t
+ e.f(t)
heap.Pop(events)
e = events[0]
}
}
}
+// Test the basic function calling behavior. Correct queueing
+// behavior is tested elsewhere, since After and AfterFunc share
+// the same code.
+func TestAfterFunc(t *testing.T) {
+ i := 10
+ c := make(chan bool)
+ var f func()
+ f = func() {
+ i--
+ if i >= 0 {
+ AfterFunc(0, f)
+ Sleep(1e9)
+ } else {
+ c <- true
+ }
+ }
+
+ AfterFunc(0, f)
+ <-c
+}
+
+func BenchmarkAfterFunc(b *testing.B) {
+ i := b.N
+ c := make(chan bool)
+ var f func()
+ f = func() {
+ i--
+ if i >= 0 {
+ AfterFunc(0, f)
+ } else {
+ c <- true
+ }
+ }
+
+ AfterFunc(0, f)
+ <-c
+}
+
func TestAfter(t *testing.T) {
const delay = int64(100e6)
start := Nanoseconds()