Hilbish/timer.go

124 lines
1.9 KiB
Go

package main
import (
"errors"
"fmt"
"os"
"time"
rt "github.com/arnodel/golua/runtime"
)
type timerType int64
const (
timerInterval timerType = iota
timerTimeout
)
// #interface timers
// #property type What type of timer it is
// #property running If the timer is running
// #property duration The duration in milliseconds that the timer will run
// Timer type.
type timer struct{
id int
typ timerType
running bool
dur time.Duration
fun *rt.Closure
th *timersModule
ticker *time.Ticker
ud *rt.UserData
channel chan struct{}
}
func (t *timer) start() error {
if t.running {
return errors.New("timer is already running")
}
t.running = true
t.th.running++
t.th.wg.Add(1)
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 <- struct{}{}
t.running = false
t.th.running--
t.th.wg.Done()
return nil
}
// #interface timers
// #member
// start()
// Starts a timer.
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
}
return c.Next(), nil
}
// #interface timers
// #member
// stop()
// Stops a timer.
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
}