Skip to content

Commit a2b7e56

Browse files
authored
Reduce memory allocations in add function (#4)
1 parent 4be16d1 commit a2b7e56

1 file changed

Lines changed: 21 additions & 8 deletions

File tree

debounce.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ func New(after time.Duration, options ...Option) func(f func()) {
4444
callsLimit: -1,
4545
}
4646

47+
// Creating timer and immediatly stop it, so there will be always allocated Timer
48+
d.timer = time.AfterFunc(math.MaxInt64, func() {
49+
d.f()
50+
})
51+
d.timer.Stop()
52+
4753
for _, opt := range options {
4854
opt(d)
4955
}
@@ -63,6 +69,9 @@ type debouncer struct {
6369

6470
startWait time.Time
6571
waitLimit time.Duration
72+
73+
// Stores last function to debounce. Will be called after specified duration.
74+
f func()
6675
}
6776

6877
func (d *debouncer) callLimitReached() bool {
@@ -77,21 +86,25 @@ func (d *debouncer) add(f func()) {
7786
d.mu.Lock()
7887
defer d.mu.Unlock()
7988

80-
if d.timer != nil {
81-
d.timer.Stop()
82-
} else {
83-
d.calls = 0
89+
// Refreshing function reference, so d.timer will call right function
90+
d.f = f
91+
92+
// If this is a first call, store startWait time
93+
if d.calls == 0 {
8494
d.startWait = time.Now()
8595
}
8696

97+
// Counting calls
8798
d.calls += 1
8899

89100
// If the function has been called more than the limit, or if the wait time
90101
// has exceeded the limit, execute the function immediately.
91102
if d.callLimitReached() || d.timeLimitReached() {
92-
d.timer = nil
93-
f()
94-
} else { // Otherwise, set a timer to call the function after the specified duration.
95-
d.timer = time.AfterFunc(d.after, f)
103+
d.timer.Stop()
104+
d.calls = 0
105+
d.f()
106+
} else {
107+
// Restarting timer, if limits were ok
108+
d.timer.Reset(d.after)
96109
}
97110
}

0 commit comments

Comments
 (0)