mirror of https://github.com/golang/go.git
72 lines
1.4 KiB
Go
72 lines
1.4 KiB
Go
// 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
|
|
}
|