From e656b8f21042396e171ddb1101d86d150a80d5b4 Mon Sep 17 00:00:00 2001 From: TorchedSammy <38820196+TorchedSammy@users.noreply.github.com> Date: Sat, 28 May 2022 17:17:59 -0400 Subject: [PATCH] refactor!: use userdata for timer objects --- api.go | 4 +-- timer.go | 46 +++++++++++++++++----------------- timerhandler.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 26 deletions(-) diff --git a/api.go b/api.go index 9289305..3aca037 100644 --- a/api.go +++ b/api.go @@ -476,7 +476,7 @@ func hltimeout(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { timer := timers.create(timerTimeout, interval, cb) timer.start() - return c.PushingNext1(t.Runtime, timer.lua()), nil + return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil } // interval(cb, time) @@ -502,7 +502,7 @@ func hlinterval(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { timer := timers.create(timerInterval, interval, cb) timer.start() - return c.PushingNext1(t.Runtime, timer.lua()), nil + return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil } // complete(scope, cb) diff --git a/timer.go b/timer.go index a502087..74d13c4 100644 --- a/timer.go +++ b/timer.go @@ -6,8 +6,6 @@ import ( "os" "time" - "hilbish/util" - rt "github.com/arnodel/golua/runtime" ) @@ -25,6 +23,7 @@ type timer struct{ fun *rt.Closure th *timerHandler ticker *time.Ticker + ud *rt.UserData channel chan struct{} } @@ -74,8 +73,17 @@ func (t *timer) stop() error { return nil } -func (t *timer) luaStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { - err := t.start() +func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { + if err := c.Check1Arg(); err != nil { + return nil, err + } + + t, err := timerArg(c, 0) + if err != nil { + return nil, err + } + + err = t.start() if err != nil { return nil, err } @@ -83,26 +91,20 @@ func (t *timer) luaStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } -func (t *timer) luaStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { - err := t.stop() +func timerStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { + if err := c.Check1Arg(); err != nil { + return nil, err + } + + t, err := timerArg(c, 0) if err != nil { return nil, err } - + + err = t.stop() + if err != nil { + return nil, err + } + return c.Next(), nil } - -func (t *timer) lua() rt.Value { - tExports := map[string]util.LuaExport{ - "start": {t.luaStart, 0, false}, - "stop": {t.luaStop, 0, false}, - } - luaTimer := rt.NewTable() - util.SetExports(l, luaTimer, tExports) - - luaTimer.Set(rt.StringValue("type"), rt.IntValue(int64(t.typ))) - luaTimer.Set(rt.StringValue("running"), rt.BoolValue(t.running)) - luaTimer.Set(rt.StringValue("duration"), rt.IntValue(int64(t.dur / time.Millisecond))) - - return rt.TableValue(luaTimer) -} diff --git a/timerhandler.go b/timerhandler.go index 2f2e878..64caff8 100644 --- a/timerhandler.go +++ b/timerhandler.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "sync" "time" @@ -10,6 +11,8 @@ import ( ) var timers *timerHandler +var timerMetaKey = rt.StringValue("hshtimer") + type timerHandler struct { mu *sync.RWMutex wg *sync.WaitGroup @@ -44,6 +47,8 @@ func (th *timerHandler) create(typ timerType, dur time.Duration, fun *rt.Closure th: th, id: th.latestID, } + t.ud = timerUserData(t) + th.timers[th.latestID] = t return t @@ -75,7 +80,7 @@ func (th *timerHandler) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { timerTyp := timerType(timerTypInt) tmr := th.create(timerTyp, time.Duration(ms) * time.Millisecond, cb) - return c.PushingNext1(t.Runtime, tmr.lua()), nil + return c.PushingNext1(t.Runtime, rt.UserDataValue(tmr.ud)), nil } func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { @@ -89,13 +94,45 @@ func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { t := th.get(int(id)) if t != nil { - return c.PushingNext1(thr.Runtime, t.lua()), nil + return c.PushingNext1(thr.Runtime, rt.UserDataValue(t.ud)), nil } return c.Next(), nil } func (th *timerHandler) loader(rtm *rt.Runtime) *rt.Table { + timerMethods := rt.NewTable() + timerFuncs := map[string]util.LuaExport{ + "start": {timerStart, 1, false}, + "stop": {timerStop, 1, false}, + } + util.SetExports(rtm, timerMethods, timerFuncs) + + timerMeta := rt.NewTable() + timerIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { + ti, _ := timerArg(c, 0) + + arg := c.Arg(1) + val := timerMethods.Get(arg) + + if val != rt.NilValue { + return c.PushingNext1(t.Runtime, val), nil + } + + keyStr, _ := arg.TryString() + + switch keyStr { + case "type": val = rt.IntValue(int64(ti.typ)) + case "running": val = rt.BoolValue(ti.running) + case "duration": val = rt.IntValue(int64(ti.dur / time.Millisecond)) + } + + return c.PushingNext1(t.Runtime, val), nil + } + + timerMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(timerIndex, "__index", 2, false))) + l.SetRegistry(timerMetaKey, rt.TableValue(timerMeta)) + thExports := map[string]util.LuaExport{ "create": {th.luaCreate, 3, false}, "get": {th.luaGet, 1, false}, @@ -106,3 +143,27 @@ func (th *timerHandler) loader(rtm *rt.Runtime) *rt.Table { return luaTh } + +func timerArg(c *rt.GoCont, arg int) (*timer, error) { + j, ok := valueToTimer(c.Arg(arg)) + if !ok { + return nil, fmt.Errorf("#%d must be a timer", arg + 1) + } + + return j, nil +} + +func valueToTimer(val rt.Value) (*timer, bool) { + u, ok := val.TryUserData() + if !ok { + return nil, false + } + + j, ok := u.Value().(*timer) + return j, ok +} + +func timerUserData(j *timer) *rt.UserData { + timerMeta := l.Registry(timerMetaKey) + return rt.NewUserData(j, timerMeta.AsTable()) +}