From b1028cd108748e82b04257e96ebb1f539124b8ac Mon Sep 17 00:00:00 2001 From: Corey Butler Date: Mon, 21 Oct 2019 14:32:07 -0500 Subject: [PATCH] Fixed endless loop on settimeout. --- .travis.yml | 2 +- timer.go | 30 ++++++++++++++++++++++++------ timer_test.go | 40 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1f727c5..2fa9224 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,4 +16,4 @@ install: - # Skip script: - - go test + - go test -v diff --git a/timer.go b/timer.go index d3292ad..d4b0ce4 100644 --- a/timer.go +++ b/timer.go @@ -1,6 +1,8 @@ package timer -import "time" +import ( + "time" +) // Timer represents a monitor/iterator that runs // a function on a given interval. @@ -21,6 +23,11 @@ func (timer *Timer) Start() { return } + if timer.process != nil { + close(timer.process) + } + + timer.running = true timer.process = make(chan struct{}) timer.ticker = time.NewTicker(timer.interval) timer.iterations = 0 @@ -31,31 +38,42 @@ func (timer *Timer) Start() { select { case <-timer.ticker.C: go func(timer *Timer) { + if !timer.running { + return + } + timer.iterations = timer.iterations + 1 - if timer.maxIntervals >= 0 && timer.iterations > timer.maxIntervals { + if timer.maxIntervals > 0 && timer.iterations > timer.maxIntervals { timer.Stop() return } timer.fn(timer.args) + + if timer.maxIntervals == 0 { + timer.Stop() + return + } }(timer) case <-timer.process: timer.Stop() return } + } else { + return } } }(timer) - - timer.running = true } // Stop the timer. func (timer *Timer) Stop() { - close(timer.process) - timer.running = false + if timer.running { + close(timer.process) + timer.running = false + } } // Count represents the number of times the interval has been processed. diff --git a/timer_test.go b/timer_test.go index 78bdc27..6912893 100644 --- a/timer_test.go +++ b/timer_test.go @@ -11,7 +11,7 @@ func TestInterval(t *testing.T) { counter = counter + 1 }, 300, &counter) - time.AfterFunc(time.Duration(1)*time.Second, func() { + timer := time.AfterFunc(time.Duration(1)*time.Second, func() { if counter < 3 { t.Errorf("Expected interval to run 3 times within a second. Only ran %v", counter) } @@ -19,7 +19,13 @@ func TestInterval(t *testing.T) { if counter != interval.Count() { t.Errorf("Expected %v iterations, only counted %v", counter, interval.Count()) } + + interval.Stop() }) + + defer timer.Stop() + + time.Sleep(time.Duration(1400) * time.Millisecond) } func TestTimeout(t *testing.T) { @@ -28,7 +34,7 @@ func TestTimeout(t *testing.T) { counter = counter + 1 }, 300, &counter) - time.AfterFunc(time.Duration(1)*time.Second, func() { + timer := time.AfterFunc(time.Duration(1)*time.Second, func() { if counter > 1 { t.Errorf("Expected timeout to run once within a second. # Times Run: %v", counter) } @@ -37,4 +43,34 @@ func TestTimeout(t *testing.T) { t.Errorf("Expected %v iterations, only counted %v", counter, interval.Count()) } }) + + defer timer.Stop() + + time.Sleep(time.Duration(500) * time.Millisecond) +} + +func TestMultipleTimers(t *testing.T) { + counter := 0 + var counterFn func(args ...interface{}) + + counterFn = func(args ...interface{}) { + counter = counter + 1 + + if counter < 3 { + _ = SetTimeout(counterFn, 300) + } + } + + _ = SetTimeout(counterFn, 300) + + timer := time.AfterFunc(time.Duration(2)*time.Second, func() { + if counter != 3 { + t.Errorf("Expected timeout to run 3 times within a second. # Times Run: %v", counter) + t.Fail() + } + }) + + defer timer.Stop() + + time.Sleep(time.Duration(2500) * time.Millisecond) }