mirror of
				https://github.com/sammy-ette/Hilbish
				synced 2025-08-10 02:52:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			125 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package main
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"time"
 | |
| 
 | |
| 	rt "github.com/arnodel/golua/runtime"
 | |
| )
 | |
| 
 | |
| type timerType int64
 | |
| const (
 | |
| 	timerInterval timerType = iota
 | |
| 	timerTimeout
 | |
| )
 | |
| 
 | |
| // #type
 | |
| // #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
 | |
| // The Job type describes a Hilbish timer.
 | |
| 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
 | |
| }
 |