2022-04-12 23:28:25 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
rt "github.com/arnodel/golua/runtime"
|
|
|
|
)
|
|
|
|
|
|
|
|
type timerType int64
|
|
|
|
const (
|
|
|
|
timerInterval timerType = iota
|
|
|
|
timerTimeout
|
|
|
|
)
|
|
|
|
|
2023-01-07 16:57:34 +00:00
|
|
|
// #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.
|
2022-04-12 23:28:25 +00:00
|
|
|
type timer struct{
|
|
|
|
id int
|
|
|
|
typ timerType
|
|
|
|
running bool
|
|
|
|
dur time.Duration
|
|
|
|
fun *rt.Closure
|
2022-12-15 04:00:54 +00:00
|
|
|
th *timersModule
|
2022-04-12 23:28:25 +00:00
|
|
|
ticker *time.Ticker
|
2022-05-28 23:03:44 +00:00
|
|
|
ud *rt.UserData
|
2022-05-22 01:39:14 +00:00
|
|
|
channel chan struct{}
|
2022-04-12 23:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *timer) start() error {
|
|
|
|
if t.running {
|
|
|
|
return errors.New("timer is already running")
|
|
|
|
}
|
|
|
|
|
|
|
|
t.running = true
|
|
|
|
t.th.running++
|
2022-05-22 01:58:58 +00:00
|
|
|
t.th.wg.Add(1)
|
2022-04-12 23:28:25 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2022-05-22 01:39:14 +00:00
|
|
|
t.channel <- struct{}{}
|
2022-04-12 23:28:25 +00:00
|
|
|
t.running = false
|
|
|
|
t.th.running--
|
2022-05-22 01:58:58 +00:00
|
|
|
t.th.wg.Done()
|
2022-04-12 23:28:25 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-12-15 04:00:54 +00:00
|
|
|
// #interface timers
|
|
|
|
// #member
|
|
|
|
// start()
|
|
|
|
// Starts a timer.
|
2022-05-28 23:03:44 +00:00
|
|
|
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)
|
2022-04-12 23:28:25 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-05-28 23:03:44 +00:00
|
|
|
err = t.start()
|
2022-04-12 23:28:25 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.Next(), nil
|
|
|
|
}
|
|
|
|
|
2022-12-15 04:00:54 +00:00
|
|
|
// #interface timers
|
|
|
|
// #member
|
|
|
|
// stop()
|
|
|
|
// Stops a timer.
|
2022-05-28 23:03:44 +00:00
|
|
|
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
|
2022-04-12 23:28:25 +00:00
|
|
|
}
|
|
|
|
|
2022-05-28 23:03:44 +00:00
|
|
|
err = t.stop()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-04-12 23:28:25 +00:00
|
|
|
|
2022-05-28 23:03:44 +00:00
|
|
|
return c.Next(), nil
|
2022-04-12 23:28:25 +00:00
|
|
|
}
|