pax_global_header00006660000000000000000000000064134252734400014516gustar00rootroot0000000000000052 comment=bf07a0f9e25545ee1b5974845f70185f91b72a00 debounce-1.2.0/000077500000000000000000000000001342527344000133025ustar00rootroot00000000000000debounce-1.2.0/.gitignore000066400000000000000000000004371342527344000152760ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof cover.out nohup.out debounce-1.2.0/.travis.yml000066400000000000000000000004301342527344000154100ustar00rootroot00000000000000language: go sudo: false go: - "1.11.x" - tip os: - linux - osx matrix: allow_failures: - go: tip fast_finish: true script: - env GO111MODULE=on go test -race -coverprofile=coverage.txt -covermode=atomic after_success: - bash <(curl -s https://codecov.io/bash)debounce-1.2.0/LICENSE000066400000000000000000000020771342527344000143150ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2016 Bjørn Erik Pedersen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. debounce-1.2.0/README.md000066400000000000000000000017261342527344000145670ustar00rootroot00000000000000# Go Debounce [![Build Status](https://travis-ci.org/bep/debounce.svg)](https://travis-ci.org/bep/debounce) [![GoDoc](https://godoc.org/github.com/bep/debounce?status.svg)](https://godoc.org/github.com/bep/debounce) [![Go Report Card](https://goreportcard.com/badge/github.com/bep/debounce)](https://goreportcard.com/report/github.com/bep/debounce) [![codecov](https://codecov.io/gh/bep/debounce/branch/master/graph/badge.svg)](https://codecov.io/gh/bep/debounce) [![Release](https://img.shields.io/github/release/bep/debounce.svg?style=flat-square)](https://github.com/bep/debounce/releases/latest) ## Example ```go func ExampleNew() { var counter uint64 f := func() { atomic.AddUint64(&counter, 1) } debounced := debounce.New(100 * time.Millisecond) for i := 0; i < 3; i++ { for j := 0; j < 10; j++ { debounced(f) } time.Sleep(200 * time.Millisecond) } c := int(atomic.LoadUint64(&counter)) fmt.Println("Counter is", c) // Output: Counter is 3 } ``` debounce-1.2.0/debounce.go000066400000000000000000000020401342527344000154110ustar00rootroot00000000000000// Copyright © 2019 Bjørn Erik Pedersen . // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. // Package debounce provides a debouncer func. The most typical use case would be // the user typing a text into a form; the UI needs an update, but let's wait for // a break. package debounce import ( "sync" "time" ) // New returns a debounced function that takes another functions as its argument. // This function will be called when the debounced function stops being called // for the given duration. // The debounced function can be invoked with different functions, if needed, // the last one will win. func New(after time.Duration) func(f func()) { d := &debouncer{after: after} return func(f func()) { d.add(f) } } type debouncer struct { mu sync.Mutex after time.Duration timer *time.Timer } func (d *debouncer) add(f func()) { d.mu.Lock() defer d.mu.Unlock() if d.timer != nil { d.timer.Stop() } d.timer = time.AfterFunc(d.after, f) } debounce-1.2.0/debounce_test.go000066400000000000000000000044761342527344000164670ustar00rootroot00000000000000package debounce_test import ( "fmt" "sync" "sync/atomic" "testing" "time" "github.com/bep/debounce" ) func TestDebounce(t *testing.T) { var ( counter1 uint64 counter2 uint64 ) f1 := func() { atomic.AddUint64(&counter1, 1) } f2 := func() { atomic.AddUint64(&counter2, 1) } f3 := func() { atomic.AddUint64(&counter2, 2) } debounced := debounce.New(100 * time.Millisecond) for i := 0; i < 3; i++ { for j := 0; j < 10; j++ { debounced(f1) } time.Sleep(200 * time.Millisecond) } for i := 0; i < 4; i++ { for j := 0; j < 10; j++ { debounced(f2) } for j := 0; j < 10; j++ { debounced(f3) } time.Sleep(200 * time.Millisecond) } c1 := int(atomic.LoadUint64(&counter1)) c2 := int(atomic.LoadUint64(&counter2)) if c1 != 3 { t.Error("Expected count 3, was", c1) } if c2 != 8 { t.Error("Expected count 8, was", c2) } } func TestDebounceConcurrentAdd(t *testing.T) { var wg sync.WaitGroup var flag uint64 debounced := debounce.New(100 * time.Millisecond) for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() debounced(func() { atomic.CompareAndSwapUint64(&flag, 0, 1) }) }() } wg.Wait() time.Sleep(500 * time.Millisecond) c := int(atomic.LoadUint64(&flag)) if c != 1 { t.Error("Flag not set") } } // Issue #1 func TestDebounceDelayed(t *testing.T) { var ( counter1 uint64 ) f1 := func() { atomic.AddUint64(&counter1, 1) } debounced := debounce.New(100 * time.Millisecond) time.Sleep(110 * time.Millisecond) debounced(f1) time.Sleep(200 * time.Millisecond) c1 := int(atomic.LoadUint64(&counter1)) if c1 != 1 { t.Error("Expected count 1, was", c1) } } func BenchmarkDebounce(b *testing.B) { var counter uint64 f := func() { atomic.AddUint64(&counter, 1) } debounced := debounce.New(100 * time.Millisecond) b.ResetTimer() for i := 0; i < b.N; i++ { debounced(f) } c := int(atomic.LoadUint64(&counter)) if c != 0 { b.Fatal("Expected count 0, was", c) } } func ExampleNew() { var counter uint64 f := func() { atomic.AddUint64(&counter, 1) } debounced := debounce.New(100 * time.Millisecond) for i := 0; i < 3; i++ { for j := 0; j < 10; j++ { debounced(f) } time.Sleep(200 * time.Millisecond) } c := int(atomic.LoadUint64(&counter)) fmt.Println("Counter is", c) // Output: Counter is 3 } debounce-1.2.0/go.mod000066400000000000000000000000371342527344000144100ustar00rootroot00000000000000module github.com/bep/debounce debounce-1.2.0/go.sum000066400000000000000000000000001342527344000144230ustar00rootroot00000000000000