82 lines
2.0 KiB
Go
82 lines
2.0 KiB
Go
package task
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"runtime"
|
|
"sync"
|
|
)
|
|
|
|
type TaskTarget struct {
|
|
Name string
|
|
targetFunc interface{}
|
|
paramTypes map[string]reflect.Type
|
|
}
|
|
|
|
// Params returns the list of parameter types
|
|
func (t *TaskTarget) Params() []reflect.Type {
|
|
ft := reflect.TypeOf(t.targetFunc)
|
|
paramTypes := make([]reflect.Type, ft.NumIn())
|
|
for idx := 0; idx < ft.NumIn(); idx++ {
|
|
in := ft.In(idx)
|
|
paramTypes[idx] = in
|
|
}
|
|
return paramTypes
|
|
}
|
|
|
|
type TaskTargetRegistry struct {
|
|
targetFuncs sync.Map
|
|
}
|
|
|
|
// Add appends the function to the registry after resolving specific information about this function.
|
|
func (r *TaskTargetRegistry) Add(targetFunc interface{}) (*TaskTarget, error) {
|
|
fv := reflect.ValueOf(targetFunc)
|
|
if fv.Kind() != reflect.Func {
|
|
return nil, fmt.Errorf("Provided function value is not an actual function")
|
|
}
|
|
|
|
name := runtime.FuncForPC(fv.Pointer()).Name()
|
|
funcInstance, err := r.Get(name)
|
|
if err == nil {
|
|
return funcInstance, nil
|
|
}
|
|
|
|
taskTarget := &TaskTarget{
|
|
Name: name,
|
|
targetFunc: targetFunc,
|
|
paramTypes: r.resolveParamTypes(targetFunc),
|
|
}
|
|
|
|
r.targetFuncs.Store(name, taskTarget)
|
|
|
|
return taskTarget, nil
|
|
}
|
|
|
|
// Get returns the TaskTarget instance which holds all information about any single registered task function.
|
|
func (r *TaskTargetRegistry) Get(name string) (*TaskTarget, error) {
|
|
taskTarget, ok := r.targetFuncs.Load(name)
|
|
if ok {
|
|
return taskTarget.(*TaskTarget), nil
|
|
}
|
|
return nil, fmt.Errorf("Function %s not found", name)
|
|
}
|
|
|
|
// Exists checks if a function with provided name exists.
|
|
func (r *TaskTargetRegistry) Exists(name string) bool {
|
|
_, ok := r.targetFuncs.Load(name)
|
|
if ok {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (r *TaskTargetRegistry) resolveParamTypes(targetFunc interface{}) map[string]reflect.Type {
|
|
paramTypes := make(map[string]reflect.Type)
|
|
funcType := reflect.TypeOf(targetFunc)
|
|
for idx := 0; idx < funcType.NumIn(); idx++ {
|
|
in := funcType.In(idx)
|
|
paramTypes[in.Name()] = in
|
|
}
|
|
return paramTypes
|
|
}
|