mirror of
https://github.com/safing/portbase
synced 2025-09-01 18:19:57 +00:00
154 lines
3 KiB
Go
154 lines
3 KiB
Go
// Copyright Safing ICS Technologies GmbH. Use of this source code is governed by the AGPL license that can be found in the LICENSE file.
|
|
|
|
package taskmanager
|
|
|
|
import (
|
|
"container/list"
|
|
"time"
|
|
|
|
"github.com/tevino/abool"
|
|
)
|
|
|
|
type Task struct {
|
|
name string
|
|
start chan bool
|
|
started *abool.AtomicBool
|
|
schedule *time.Time
|
|
}
|
|
|
|
var taskQueue *list.List
|
|
var prioritizedTaskQueue *list.List
|
|
var addToQueue chan *Task
|
|
var addToPrioritizedQueue chan *Task
|
|
var addAsNextTask chan *Task
|
|
|
|
var finishedQueuedTask chan bool
|
|
var queuedTaskRunning *abool.AtomicBool
|
|
|
|
var getQueueLengthREQ chan bool
|
|
var getQueueLengthREP chan int
|
|
|
|
func newUnqeuedTask(name string) *Task {
|
|
t := &Task{
|
|
name,
|
|
make(chan bool),
|
|
abool.NewBool(false),
|
|
nil,
|
|
}
|
|
return t
|
|
}
|
|
|
|
func NewQueuedTask(name string) *Task {
|
|
t := newUnqeuedTask(name)
|
|
addToQueue <- t
|
|
return t
|
|
}
|
|
|
|
func NewPrioritizedQueuedTask(name string) *Task {
|
|
t := newUnqeuedTask(name)
|
|
addToPrioritizedQueue <- t
|
|
return t
|
|
}
|
|
|
|
func (t *Task) addToPrioritizedQueue() {
|
|
addToPrioritizedQueue <- t
|
|
}
|
|
|
|
func (t *Task) WaitForStart() chan bool {
|
|
return t.start
|
|
}
|
|
|
|
func (t *Task) StartAnyway() {
|
|
addAsNextTask <- t
|
|
}
|
|
|
|
func (t *Task) Done() {
|
|
if !t.started.SetToIf(false, true) {
|
|
finishedQueuedTask <- true
|
|
}
|
|
}
|
|
|
|
func TotalQueuedTasks() int {
|
|
getQueueLengthREQ <- true
|
|
return <-getQueueLengthREP
|
|
}
|
|
|
|
func checkQueueStatus() {
|
|
if queuedTaskRunning.SetToIf(false, true) {
|
|
finishedQueuedTask <- true
|
|
}
|
|
}
|
|
|
|
func fireNextTask() {
|
|
|
|
if prioritizedTaskQueue.Len() > 0 {
|
|
for e := prioritizedTaskQueue.Front(); prioritizedTaskQueue.Len() > 0; e.Next() {
|
|
t := e.Value.(*Task)
|
|
prioritizedTaskQueue.Remove(e)
|
|
if t.started.SetToIf(false, true) {
|
|
close(t.start)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if taskQueue.Len() > 0 {
|
|
for e := taskQueue.Front(); taskQueue.Len() > 0; e.Next() {
|
|
t := e.Value.(*Task)
|
|
taskQueue.Remove(e)
|
|
if t.started.SetToIf(false, true) {
|
|
close(t.start)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
queuedTaskRunning.UnSet()
|
|
|
|
}
|
|
|
|
func init() {
|
|
|
|
taskQueue = list.New()
|
|
prioritizedTaskQueue = list.New()
|
|
addToQueue = make(chan *Task, 1)
|
|
addToPrioritizedQueue = make(chan *Task, 1)
|
|
addAsNextTask = make(chan *Task, 1)
|
|
|
|
finishedQueuedTask = make(chan bool, 1)
|
|
queuedTaskRunning = abool.NewBool(false)
|
|
|
|
getQueueLengthREQ = make(chan bool, 1)
|
|
getQueueLengthREP = make(chan int, 1)
|
|
|
|
go func() {
|
|
|
|
for {
|
|
select {
|
|
case <-shutdownSignal:
|
|
// TODO: work off queue?
|
|
return
|
|
case <-getQueueLengthREQ:
|
|
// TODO: maybe clean queues before replying
|
|
if queuedTaskRunning.IsSet() {
|
|
getQueueLengthREP <- prioritizedTaskQueue.Len() + taskQueue.Len() + 1
|
|
} else {
|
|
getQueueLengthREP <- prioritizedTaskQueue.Len() + taskQueue.Len()
|
|
}
|
|
case t := <-addToQueue:
|
|
taskQueue.PushBack(t)
|
|
checkQueueStatus()
|
|
case t := <-addToPrioritizedQueue:
|
|
prioritizedTaskQueue.PushBack(t)
|
|
checkQueueStatus()
|
|
case t := <-addAsNextTask:
|
|
prioritizedTaskQueue.PushFront(t)
|
|
checkQueueStatus()
|
|
case <-finishedQueuedTask:
|
|
fireNextTask()
|
|
}
|
|
}
|
|
|
|
}()
|
|
|
|
}
|