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  }