-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlua_core.go
121 lines (109 loc) · 2.01 KB
/
lua_core.go
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package lua
import (
"container/list"
"runtime"
"sync"
)
var (
core *gLuaCore
coreOnce sync.Once
)
// one LuaJit vm per core
type gLuaCore struct {
queue chan *gLuaContext
vms *list.List
idles chan *gLuaVM
waitting []*gLuaContext
callback map[int64][]*gLuaContext
}
func getCore() *gLuaCore {
coreOnce.Do(func() {
count := runtime.NumCPU()
//count := 2
core = &gLuaCore{
queue: make(chan *gLuaContext, 128),
vms: list.New(),
idles: make(chan *gLuaVM, count),
waitting: make([]*gLuaContext, 0),
callback: make(map[int64][]*gLuaContext),
}
for i := 0; i < count; i++ {
vm := newGLuaVM()
core.vms.PushBack(vm)
}
go core.loop()
})
return core
}
func (c *gLuaCore) push(ctx *gLuaContext) {
c.queue <- ctx
}
func (c *gLuaCore) loop() {
for {
select {
case ctx := <-c.queue:
if ctx.vmId == 0 {
c.waitting = append(c.waitting, ctx)
} else {
target, ok := c.callback[ctx.vmId]
if false == ok {
target = []*gLuaContext{ctx}
} else {
target = append(target, ctx)
}
c.callback[ctx.vmId] = target
}
c.scheduler()
case vm := <-c.idles:
c.vms.PushBack(vm)
c.scheduler()
}
}
}
func (c *gLuaCore) scheduler() {
current := c.vms.Front()
for {
if current == nil {
return
}
vm := current.Value.(*gLuaVM)
target := c.callback[vm.id]
if len(target) > 0 {
temp := current.Next()
c.vms.Remove(current)
current = temp
ctx := target[0]
if len(target) > 1 {
c.callback[vm.id] = target[1:]
} else {
c.callback[vm.id] = []*gLuaContext{}
}
go func() {
defer func() {
c.idles <- vm
}()
vm.process(ctx)
}()
continue
}
if len(c.waitting) == 0 {
current = current.Next()
continue
}
temp := current.Next()
c.vms.Remove(current)
current = temp
ctx := c.waitting[0]
if len(target) > 1 {
c.waitting = c.waitting[1:]
} else {
c.waitting = []*gLuaContext{}
}
go func() {
defer func() {
c.idles <- vm
}()
vm.process(ctx)
}()
}
}