2
2
mirror of https://github.com/Hilbis/Hilbish synced 2025-05-21 19:53:23 +00:00
Hilbish/timer.go
TorchedSammy c95ff42dee
feat: add timer pool and api (closes #135)
adds a map (but lets call it a pool) of all
running timers. this makes us able to keep
track of all running intervals and timeouts.
it also means hilbish can wait for them to
be done before exiting (it only waits when
non interactive).

this introduces the `hilbish.timers` interface,
documented by `doc timers`. the `hilbish.interval`
and `hilbish.timeout` functions return a timer
object now.
2022-04-12 19:31:48 -04:00

107 lines
1.8 KiB
Go

package main
import (
"errors"
"fmt"
"os"
"time"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
)
type timerType int64
const (
timerInterval timerType = iota
timerTimeout
)
type timer struct{
id int
typ timerType
running bool
dur time.Duration
fun *rt.Closure
th *timerHandler
ticker *time.Ticker
channel chan bool
}
func (t *timer) start() error {
if t.running {
return errors.New("timer is already running")
}
t.running = true
t.th.running++
t.ticker = time.NewTicker(t.dur)
go func() {
for {
select {
case <-t.ticker.C:
_, err := rt.Call1(l.MainThread(), rt.FunctionValue(t.fun))
if err != nil {
fmt.Fprintln(os.Stderr, "Error in function:\n", err)
t.stop()
}
// only run one for timeout
if t.typ == timerTimeout {
t.stop()
}
case <-t.channel:
t.ticker.Stop()
return
}
}
}()
return nil
}
func (t *timer) stop() error {
if !t.running {
return errors.New("timer not running")
}
t.channel <- true
t.running = false
t.th.running--
return nil
}
func (t *timer) luaStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
err := t.start()
if err != nil {
return nil, err
}
return c.Next(), nil
}
func (t *timer) luaStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
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)
}