util-go/time/scheduler/task/registry.go
crusader 6b4beb77fb ing
2018-04-28 21:39:55 +09:00

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
}