File: debounce.go

package info (click to toggle)
golang-golang-x-tools 1%3A0.5.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bookworm-backports
  • size: 16,592 kB
  • sloc: javascript: 2,011; asm: 1,635; sh: 192; yacc: 155; makefile: 52; ansic: 8
file content (71 lines) | stat: -rw-r--r-- 1,479 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// 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
}