aboutsummaryrefslogtreecommitdiff
path: root/poll.go
blob: db00ef9561d487de29d1448f50d9b8180408d96b (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
package main

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

func doPoll(l *lua.LState, clients []*Client) (*Client, *mt.Pkt, bool) {
	var timeout time.Duration
	hasTimeout := false
	if l.GetTop() > 1 {
		timeout = time.Duration(float64(l.ToNumber(2)) * float64(time.Second))
		hasTimeout = true
	}

	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 nil, nil, false
	}

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

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

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

	if idx >= offset {
		return nil, nil, true
	}

	client := clients[idx]

	var pkt *mt.Pkt = nil
	if ok {
		pkt = value.Interface().(*mt.Pkt)
	} else {
		client.state = csDisconnected
	}

	return client, pkt, false
}