@thigasdevelopment/luam 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +616 -0
- package/lua/async.lua +119 -0
- package/lua/class.lua +178 -0
- package/lua/development-logs-client.lua +13 -0
- package/lua/development-logs-server.lua +44 -0
- package/lua/dotenv.lua +160 -0
- package/lua/env.lua +18 -0
- package/lua/math.lua +24 -0
- package/lua/string.lua +82 -0
- package/lua/table.lua +63 -0
- package/lua/threads.lua +274 -0
- package/luam.mjs +9910 -0
- package/package.json +38 -0
- package/template/README.md +120 -0
- package/template/config.lua +14 -0
- package/template/env +11 -0
- package/template/framework/bootstrap-client.luam +9 -0
- package/template/framework/bootstrap-server.luam +9 -0
- package/template/framework/command.luam +54 -0
- package/template/framework/core.luam +58 -0
- package/template/framework/event.luam +39 -0
- package/template/framework/listener.luam +40 -0
- package/template/framework/loader.luam +73 -0
- package/template/framework/thread-pool.luam +27 -0
- package/template/gitignore +7 -0
- package/template/luam.json +11 -0
- package/template/src/client/commands/ping-command.luam +8 -0
- package/template/src/client/main.luam +5 -0
- package/template/src/server/commands/hello-command.luam +9 -0
- package/template/src/server/handlers/player-join-listener.luam +9 -0
- package/template/src/server/main.luam +11 -0
- package/template/src/shared/config.luam +5 -0
- package/template/src/shared/framework/command.luam +54 -0
- package/template/src/shared/framework/core.luam +58 -0
- package/template/src/shared/framework/event.luam +39 -0
- package/template/src/shared/framework/listener.luam +40 -0
- package/template/src/shared/framework/loader.luam +73 -0
- package/template/src/shared/framework/thread-pool.luam +27 -0
package/lua/threads.lua
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
local PRIORITIES = {
|
|
2
|
+
low = { pulsing = 250, frame = 8 },
|
|
3
|
+
normal = { pulsing = 100, frame = 15 },
|
|
4
|
+
high = { pulsing = 50, frame = 25 },
|
|
5
|
+
extreme = { pulsing = 0, frame = 50 },
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
local STYLES = {
|
|
9
|
+
concurrent = true,
|
|
10
|
+
priority = true,
|
|
11
|
+
sequential = true,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function sleep(milliseconds)
|
|
15
|
+
milliseconds = tonumber(milliseconds) or 0
|
|
16
|
+
|
|
17
|
+
if milliseconds < 1 then
|
|
18
|
+
coroutine.yield()
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
local start = getTickCount()
|
|
23
|
+
|
|
24
|
+
repeat
|
|
25
|
+
coroutine.yield()
|
|
26
|
+
until (getTickCount() - start) >= milliseconds
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
local Thread = {}
|
|
30
|
+
Thread.__index = Thread
|
|
31
|
+
|
|
32
|
+
function Thread:get()
|
|
33
|
+
return self.priority
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
function Thread:set(priority)
|
|
37
|
+
priority = tonumber(priority)
|
|
38
|
+
if not priority or self.priority == priority then
|
|
39
|
+
return false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
self.priority = priority
|
|
43
|
+
return true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
function Thread:pause()
|
|
47
|
+
if self.paused then
|
|
48
|
+
return false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
self.paused = true
|
|
52
|
+
return true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
function Thread:resume()
|
|
56
|
+
if not self.paused then
|
|
57
|
+
return false
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
self.paused = false
|
|
61
|
+
return true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
function Thread:isPaused()
|
|
65
|
+
return self.paused
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
function Thread:isStarted()
|
|
69
|
+
return self.started
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
Threads = {}
|
|
73
|
+
Threads.__index = Threads
|
|
74
|
+
|
|
75
|
+
local function resumeThread(self, id, thread)
|
|
76
|
+
if coroutine.status(thread.routine) == 'dead' then
|
|
77
|
+
self:remove(id)
|
|
78
|
+
return false
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if thread:isPaused() then
|
|
82
|
+
return false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
local success, message
|
|
86
|
+
if thread:isStarted() then
|
|
87
|
+
success, message = coroutine.resume(thread.routine, thread)
|
|
88
|
+
else
|
|
89
|
+
success, message = coroutine.resume(thread.routine, thread, unpack(thread.arguments))
|
|
90
|
+
thread.started = true
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if not success then
|
|
94
|
+
self:remove(id)
|
|
95
|
+
error('[Threads] Thread ' .. tostring(id) .. ' failed: ' .. tostring(message))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
return true
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
function Threads.new(style, priority)
|
|
102
|
+
local self = setmetatable({}, Threads)
|
|
103
|
+
|
|
104
|
+
self.threads = {}
|
|
105
|
+
self.nextId, self.currentId = 0, -1
|
|
106
|
+
self.type, self.priority = 'concurrent', 'normal'
|
|
107
|
+
self.timer = nil
|
|
108
|
+
self:setType(style)
|
|
109
|
+
self:setPriority(priority)
|
|
110
|
+
|
|
111
|
+
return self
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
function Threads:add(func, options, ...)
|
|
115
|
+
options = options or {}
|
|
116
|
+
|
|
117
|
+
local thread = setmetatable({
|
|
118
|
+
routine = coroutine.create(func),
|
|
119
|
+
arguments = { ... },
|
|
120
|
+
paused = false,
|
|
121
|
+
started = false,
|
|
122
|
+
priority = options.priority or -1,
|
|
123
|
+
}, Thread)
|
|
124
|
+
|
|
125
|
+
local id = self.nextId + 1
|
|
126
|
+
self.nextId = id
|
|
127
|
+
self.threads[id] = thread
|
|
128
|
+
|
|
129
|
+
self:start()
|
|
130
|
+
return id
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
function Threads:remove(id)
|
|
134
|
+
if not self.threads[id] then
|
|
135
|
+
return false
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if self.currentId == id then
|
|
139
|
+
self.currentId = -1
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
self.threads[id] = nil
|
|
143
|
+
return true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
function Threads:clear()
|
|
147
|
+
if next(self.threads) == nil then
|
|
148
|
+
return false
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
self.threads, self.currentId = {}, -1
|
|
152
|
+
|
|
153
|
+
self:stop()
|
|
154
|
+
return true
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
function Threads:start()
|
|
158
|
+
if isTimer(self.timer) then
|
|
159
|
+
return false
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
self.timer = setTimer(function()
|
|
163
|
+
self:process()
|
|
164
|
+
end, PRIORITIES[self.priority].pulsing, 0)
|
|
165
|
+
return true
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
function Threads:stop()
|
|
169
|
+
if isTimer(self.timer) then
|
|
170
|
+
killTimer(self.timer)
|
|
171
|
+
end
|
|
172
|
+
self.timer = nil
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
function Threads:processQueue(sorted)
|
|
176
|
+
local queue = {}
|
|
177
|
+
|
|
178
|
+
for id, thread in pairs(self.threads) do
|
|
179
|
+
queue[#queue + 1] = { id = id, thread = thread }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
if sorted then
|
|
183
|
+
table.sort(queue, function(left, right)
|
|
184
|
+
return left.thread:get() > right.thread:get()
|
|
185
|
+
end)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
local frames = 0
|
|
189
|
+
for _, item in ipairs(queue) do
|
|
190
|
+
if frames >= PRIORITIES[self.priority].frame then
|
|
191
|
+
return
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
if resumeThread(self, item.id, item.thread) then
|
|
195
|
+
frames = frames + 1
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
function Threads:processSequential()
|
|
201
|
+
if not self.threads[self.currentId] then
|
|
202
|
+
self.currentId = -1
|
|
203
|
+
|
|
204
|
+
for id in pairs(self.threads) do
|
|
205
|
+
self.currentId = id
|
|
206
|
+
break
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
local thread = self.threads[self.currentId]
|
|
211
|
+
if not thread then
|
|
212
|
+
return
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
local frames = 0
|
|
216
|
+
while frames < PRIORITIES[self.priority].frame do
|
|
217
|
+
if not resumeThread(self, self.currentId, thread) then
|
|
218
|
+
return
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
frames = frames + 1
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
function Threads:process()
|
|
226
|
+
if self.type == 'sequential' then
|
|
227
|
+
self:processSequential()
|
|
228
|
+
else
|
|
229
|
+
self:processQueue(self.type == 'priority')
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
if next(self.threads) == nil then
|
|
233
|
+
self:stop()
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
function Threads:getType()
|
|
238
|
+
return self.type
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
function Threads:setType(style)
|
|
242
|
+
if type(style) ~= 'string' then
|
|
243
|
+
return false
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
style = style:lower()
|
|
247
|
+
if not STYLES[style] or self.type == style then
|
|
248
|
+
return false
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
self.type = style
|
|
252
|
+
return true
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
function Threads:getPriority()
|
|
256
|
+
return self.priority
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
function Threads:setPriority(priority)
|
|
260
|
+
if type(priority) ~= 'string' or not PRIORITIES[priority] or self.priority == priority then
|
|
261
|
+
return false
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
self.priority = priority
|
|
265
|
+
if isTimer(self.timer) then
|
|
266
|
+
self:stop()
|
|
267
|
+
self:start()
|
|
268
|
+
end
|
|
269
|
+
return true
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
function Threads:getThread(id)
|
|
273
|
+
return self.threads[id]
|
|
274
|
+
end
|