Files
obitools4/pkg/obiblackboard/subtask.go

109 lines
2.9 KiB
Go

package obiblackboard
import (
"sync"
log "github.com/sirupsen/logrus"
)
// RepeatTask creates a new DoTask function that repeats the given task n times.
//
// It takes an integer n as input, which specifies the number of times the task should be repeated.
// It returns a new DoTask function that can be used to execute the repeated task.
//
// The returned DoTask function maintains a map of tasks to their counts and tasks.
// When a task is executed, it checks if the task has been executed before.
// If it has, it increments the count and returns the previously executed task.
// If it has not been executed before, it executes the task using the provided runner function.
// If the runner function returns nil, the task is not added to the task memory and nil is returned.
// If the runner function returns a non-nil task, it is added to the task memory with a count of 0.
// After executing the task, the function checks if the count is less than (n-1).
// If it is, the task is added back to the blackboard to be executed again.
// If the count is equal to (n-1), the task is removed from the task memory.
// Finally, the function returns the executed task.
func (runner DoTask) RepeatTask(n int) DoTask {
type memtask struct {
count int
task *Task
}
taskMemory := make(map[*Task]*memtask)
taskMemoryLock := sync.Mutex{}
if n < 1 {
log.Fatalf("Cannot repeat a task less than once (n=%d)", n)
}
st := func(bb *Blackboard, task *Task) *Task {
taskMemoryLock.Lock()
mem, ok := taskMemory[task]
if !ok {
nt := runner(bb, task)
if nt == nil {
taskMemoryLock.Unlock()
return nt
}
mem = &memtask{
count: 0,
task: nt,
}
taskMemory[task] = mem
} else {
mem.count++
}
taskMemoryLock.Unlock()
if mem.count < (n - 1) {
bb.PushTask(task)
}
if mem.count == (n - 1) {
taskMemoryLock.Lock()
delete(taskMemory, task)
taskMemoryLock.Unlock()
}
return mem.task
}
return st
}
// CombineWith returns a new DoTask function that combines the given DoTask
// functions. The returned function applies the `other` function to the result
// of the `runner` function. The `bb` parameter is the Blackboard instance,
// and the `task` parameter is the Task instance.
//
// Parameters:
// - bb: The Blackboard instance.
// - task: The Task instance.
//
// Returns:
// - *Task: The result of applying the `other` function to the result of the
// `runner` function.
func (runner DoTask) CombineWith(other DoTask) DoTask {
return func(bb *Blackboard, task *Task) *Task {
return other(bb, runner(bb, task))
}
}
// SetTarget sets the target role for the task.
//
// Parameters:
// - target: The target role to set.
//
// Returns:
// - DoTask: The modified DoTask function.
func (runner DoTask) SetTarget(target string) DoTask {
return func(bb *Blackboard, task *Task) *Task {
nt := runner(bb, task)
nt.Role = target
return nt
}
}