scouting: Change background_task implementation
Instead of manually implementing a ticker, this patch switches over to
using `time.Ticker`. The functionality should be identical.
This patch also adds a small test to make sure that the bare
functionality is working.
Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: I54acfc5280b3541f3021dbe35d79e7db0adcc5f6
diff --git a/scouting/background_task/background_task.go b/scouting/background_task/background_task.go
index 4fdb034..6980042 100644
--- a/scouting/background_task/background_task.go
+++ b/scouting/background_task/background_task.go
@@ -7,52 +7,46 @@
// A helper to run a function in the background at a specified interval.
// Can be used for a lot of different things.
type backgroundTask struct {
- doneChan chan<- bool
- checkStopped chan<- bool
- interval time.Duration
+ ticker *time.Ticker
+ stopRequested chan bool
+ done chan bool
}
func New(interval time.Duration) backgroundTask {
return backgroundTask{
- doneChan: make(chan bool, 1),
- checkStopped: make(chan bool, 1),
- interval: interval,
+ ticker: time.NewTicker(interval),
+ stopRequested: make(chan bool, 1),
+ done: make(chan bool, 1),
}
}
func (task *backgroundTask) Start(taskFunc func()) {
go func() {
- // Setting start time to a time prior so the function gets
- // called instantly when Start() called
- startTime := time.Now().Add(-task.interval - time.Minute)
+ // Signal the Stop() function below when the goroutine has
+ // finished executing.
+ defer func() { task.done <- true }()
+
+ // time.Ticker doesn't perform an immediate invocation.
+ // Instead, it waits for the specified duration before
+ // triggering the first tick. We pretend that there's a tick
+ // here by invoking the callback manually.
+ taskFunc()
+
for {
- curTime := time.Now()
- diff := curTime.Sub(startTime)
-
- if diff > task.interval {
+ select {
+ case <-task.stopRequested:
+ return
+ case <-task.ticker.C:
taskFunc()
- startTime = curTime
}
-
- if len(task.doneChan) != 0 {
- break
- }
-
- time.Sleep(time.Second)
}
-
- task.checkStopped <- true
}()
}
func (task *backgroundTask) Stop() {
- task.doneChan <- true
-
- for {
- if len(task.checkStopped) != 0 {
- close(task.doneChan)
- close(task.checkStopped)
- break
- }
- }
+ task.stopRequested <- true
+ task.ticker.Stop()
+ <-task.done
+ close(task.stopRequested)
+ close(task.done)
}