You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
1.5 KiB
84 lines
1.5 KiB
package task
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var globalCtx, globalCancel = context.WithCancel(context.Background())
|
|
|
|
// A Task is a wrapper around a function that offers scheduling
|
|
// and syncronization.
|
|
type Task struct {
|
|
mutex sync.Mutex
|
|
ctx context.Context
|
|
ctxCancel context.CancelFunc
|
|
waitDuration time.Duration
|
|
scheduled bool
|
|
callback func() error
|
|
}
|
|
|
|
// Context gets the task's context.
|
|
func (task *Task) Context() context.Context {
|
|
return task.ctx
|
|
}
|
|
|
|
// Stop stops a task. This should not be done to stop a single run,
|
|
// but as a way to cancel it forever.
|
|
func (task *Task) Stop() {
|
|
task.ctxCancel()
|
|
}
|
|
|
|
// Schedule schedules a task for later execution.
|
|
func (task *Task) Schedule() {
|
|
// Don't if the context is closed.
|
|
select {
|
|
case <-task.Context().Done():
|
|
return
|
|
default:
|
|
}
|
|
|
|
task.mutex.Lock()
|
|
if task.scheduled {
|
|
task.mutex.Unlock()
|
|
return
|
|
}
|
|
task.scheduled = true
|
|
task.mutex.Unlock()
|
|
|
|
go func() {
|
|
<-time.After(task.waitDuration)
|
|
|
|
// Mark as no longer scheduled
|
|
task.mutex.Lock()
|
|
task.scheduled = false
|
|
task.mutex.Unlock()
|
|
|
|
// Don't if the task is cancelled
|
|
select {
|
|
case <-task.Context().Done():
|
|
return
|
|
default:
|
|
}
|
|
|
|
task.callback()
|
|
}()
|
|
}
|
|
|
|
// New makes a new task with the callback.
|
|
func New(waitDuration time.Duration, callback func() error) *Task {
|
|
ctx, ctxCancel := context.WithCancel(globalCtx)
|
|
|
|
return &Task{
|
|
callback: callback,
|
|
ctx: ctx,
|
|
ctxCancel: ctxCancel,
|
|
waitDuration: waitDuration,
|
|
}
|
|
}
|
|
|
|
// StopAll stops all tasks.
|
|
func StopAll() {
|
|
globalCancel()
|
|
}
|