| // Copyright 2020 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package lsp |
| |
| import ( |
| "sync" |
| "time" |
| ) |
| |
| type debounceEvent struct { |
| order uint64 |
| done chan struct{} |
| } |
| |
| type debouncer struct { |
| mu sync.Mutex |
| events map[string]*debounceEvent |
| } |
| |
| func newDebouncer() *debouncer { |
| return &debouncer{ |
| events: make(map[string]*debounceEvent), |
| } |
| } |
| |
| // debounce returns a channel that receives a boolean reporting whether, |
| // by the time the delay channel receives a value, this call is (or will be) |
| // the most recent call with the highest order number for its key. |
| func (d *debouncer) debounce(key string, order uint64, delay <-chan time.Time) <-chan bool { |
| okc := make(chan bool, 1) |
| |
| d.mu.Lock() |
| if prev, ok := d.events[key]; ok { |
| if prev.order > order { |
| // If we have a logical ordering of events (as is the case for snapshots), |
| // don't overwrite a later event with an earlier event. |
| d.mu.Unlock() |
| okc <- false |
| return okc |
| } |
| close(prev.done) |
| } |
| done := make(chan struct{}) |
| next := &debounceEvent{ |
| order: order, |
| done: done, |
| } |
| d.events[key] = next |
| d.mu.Unlock() |
| |
| go func() { |
| ok := false |
| select { |
| case <-delay: |
| d.mu.Lock() |
| if d.events[key] == next { |
| ok = true |
| delete(d.events, key) |
| } else { |
| // The event was superseded before we acquired d.mu. |
| } |
| d.mu.Unlock() |
| case <-done: |
| } |
| okc <- ok |
| }() |
| |
| return okc |
| } |