From 99598cbd574cc346fd5408ad9ac469f00bb1967c Mon Sep 17 00:00:00 2001 From: Wendell Sun Date: Thu, 10 Feb 2022 21:53:47 +0800 Subject: [PATCH] fix the warnings for go test --race --- .github/workflows/tests.yml | 2 +- tasks.go | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3d39ea7..6d37a07 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,7 @@ jobs: run: go get -u github.com/mattn/goveralls - name: Test - run: go test -v -covermode=count -coverprofile=coverage.out ./... + run: go test --race -v -covermode=atomic -coverprofile=coverage.out ./... - name: Update Coveralls env: diff --git a/tasks.go b/tasks.go index bb15c99..8b22f7b 100644 --- a/tasks.go +++ b/tasks.go @@ -93,6 +93,8 @@ import ( // Task contains the scheduled task details and control mechanisms. This struct is used during the creation of tasks. // It allows users to control how and when tasks are executed. type Task struct { + sync.Mutex + // id is the Unique ID created for each task. This ID is generated by the Add() function. id string @@ -139,6 +141,14 @@ type Task struct { cancel context.CancelFunc } +// safeOps safely change task's data +func (t *Task) safeOps(f func()) { + t.Lock() + defer t.Unlock() + + f() +} + // Scheduler stores the internal task list and provides an interface for task management. type Scheduler struct { sync.RWMutex @@ -243,6 +253,10 @@ func (schd *Scheduler) Del(name string) { // Stop the task defer t.cancel() + + t.Lock() + defer t.Unlock() + if t.timer != nil { defer t.timer.Stop() } @@ -290,7 +304,9 @@ func (schd *Scheduler) Stop() { func (schd *Scheduler) scheduleTask(t *Task) { select { case <-time.After(time.Until(t.StartAfter)): - t.timer = time.AfterFunc(t.Interval, func() { schd.execTask(t) }) + t.safeOps(func() { + t.timer = time.AfterFunc(t.Interval, func() { schd.execTask(t) }) + }) return case <-t.ctx.Done(): return @@ -309,6 +325,8 @@ func (schd *Scheduler) execTask(t *Task) { } }() if !t.RunOnce { - t.timer.Reset(t.Interval) + t.safeOps(func() { + t.timer.Reset(t.Interval) + }) } }