GraphQL API and utilities for the rpdata project
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

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()
}