aboutsummaryrefslogtreecommitdiff
path: root/poll.go
blob: dfc30a6fa0701a3d51f8e19fb472c8571a566841 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main

import (
	"github.com/yuin/gopher-lua"
	"reflect"
	"time"
)

type Event interface {
	handle(l *lua.LState, val lua.LValue)
}

type EventTimeout struct{}

func (evt EventTimeout) handle(l *lua.LState, val lua.LValue) {
	l.SetField(val, "type", lua.LString("timeout"))
}

type EventInterrupt struct{}

func (evt EventInterrupt) handle(l *lua.LState, val lua.LValue) {
	l.SetField(val, "type", lua.LString("interrupt"))
}

func doPoll(l *lua.LState, clients []*Client) int {
	cases := make([]reflect.SelectCase, 0, len(clients)+2)

	for _, client := range clients {
		if client.state != csConnected {
			continue
		}

		cases = append(cases, reflect.SelectCase{
			Dir:  reflect.SelectRecv,
			Chan: reflect.ValueOf(client.queue),
		})
	}

	offset := len(cases)

	if offset < 1 {
		return 0
	}

	cases = append(cases, reflect.SelectCase{
		Dir:  reflect.SelectRecv,
		Chan: reflect.ValueOf(signalChannel),
	})

	if l.GetTop() > 1 {
		timeout := time.After(time.Duration(float64(l.ToNumber(2)) * float64(time.Second)))

		cases = append(cases, reflect.SelectCase{
			Dir:  reflect.SelectRecv,
			Chan: reflect.ValueOf(timeout),
		})
	}

	idx, value, _ := reflect.Select(cases)

	var evt Event
	tbl := l.NewTable()

	if idx > offset {
		evt = EventTimeout{}
	} else if idx == offset {
		evt = EventInterrupt{}
	} else {
		evt = value.Interface().(Event)
		l.SetField(tbl, "client", clients[idx].userdata)
	}

	evt.handle(l, tbl)

	l.Push(tbl)
	return 1
}