1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 type debounceFunc struct {
17 type debouncer struct {
19 funcs map[string]*debounceFunc
22 func newDebouncer() *debouncer {
24 funcs: make(map[string]*debounceFunc),
28 // debounce waits timeout before running f, if no subsequent call is made with
29 // the same key in the intervening time. If a later call to debounce with the
30 // same key occurs while the original call is blocking, the original call will
31 // return immediately without running its f.
33 // If order is specified, it will be used to order calls logically, so calls
34 // with lesser order will not cancel calls with greater order.
35 func (d *debouncer) debounce(key string, order uint64, timeout time.Duration, f func()) {
37 // Degenerate case: no debouncing.
42 // First, atomically acquire the current func, cancel it, and insert this
45 current, ok := d.funcs[key]
46 if ok && current.order > order {
47 // If we have a logical ordering of events (as is the case for snapshots),
48 // don't overwrite a later event with an earlier event.
55 done := make(chan struct{})
56 next := &debounceFunc{
63 // Next, wait to be cancelled or for our wait to expire. There is a race here
64 // that we must handle: our timer could expire while another goroutine holds
68 case <-time.After(timeout):
70 if d.funcs[key] != next {
71 // We lost the race: another event has arrived for the key and started
72 // waiting. We could reasonably choose to run f at this point, but doing
73 // nothing is simpler.