github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/lsp/debounce.go (about) 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. 4 5 package lsp 6 7 import ( 8 "sync" 9 "time" 10 ) 11 12 type debounceEvent struct { 13 order uint64 14 done chan struct{} 15 } 16 17 type debouncer struct { 18 mu sync.Mutex 19 events map[string]*debounceEvent 20 } 21 22 func newDebouncer() *debouncer { 23 return &debouncer{ 24 events: make(map[string]*debounceEvent), 25 } 26 } 27 28 // debounce returns a channel that receives a boolean reporting whether, 29 // by the time the delay channel receives a value, this call is (or will be) 30 // the most recent call with the highest order number for its key. 31 func (d *debouncer) debounce(key string, order uint64, delay <-chan time.Time) <-chan bool { 32 okc := make(chan bool, 1) 33 34 d.mu.Lock() 35 if prev, ok := d.events[key]; ok { 36 if prev.order > order { 37 // If we have a logical ordering of events (as is the case for snapshots), 38 // don't overwrite a later event with an earlier event. 39 d.mu.Unlock() 40 okc <- false 41 return okc 42 } 43 close(prev.done) 44 } 45 done := make(chan struct{}) 46 next := &debounceEvent{ 47 order: order, 48 done: done, 49 } 50 d.events[key] = next 51 d.mu.Unlock() 52 53 go func() { 54 ok := false 55 select { 56 case <-delay: 57 d.mu.Lock() 58 if d.events[key] == next { 59 ok = true 60 delete(d.events, key) 61 } else { 62 // The event was superseded before we acquired d.mu. 63 } 64 d.mu.Unlock() 65 case <-done: 66 } 67 okc <- ok 68 }() 69 70 return okc 71 }