scheduler is much faster, missing connection holding and error handling

This commit is contained in:
Ryan Ward 2022-01-26 00:03:32 -05:00
parent 472d1748ee
commit 2b122f5c77
2 changed files with 60 additions and 156 deletions

View File

@ -1033,8 +1033,8 @@ end
function thread.hold(n,opt) function thread.hold(n,opt)
thread._Requests() thread._Requests()
if type(opt)=="table" then
interval = opt.interval interval = opt.interval
if type(opt)=="table" then
if opt.cycles then if opt.cycles then
return coroutine.yield(CMD, t_holdW, opt.cycles or 1, n or dFunc, interval) return coroutine.yield(CMD, t_holdW, opt.cycles or 1, n or dFunc, interval)
elseif opt.sleep then elseif opt.sleep then
@ -1045,9 +1045,9 @@ function thread.hold(n,opt)
end end
if type(n) == "number" then if type(n) == "number" then
thread.getRunningThread().lastSleep = clock() thread.getRunningThread().lastSleep = clock()
return coroutine.yield(CMD, t_sleep, n or 0) return coroutine.yield(CMD, t_sleep, n or 0, nil, interval)
else else
return coroutine.yield(CMD, t_hold, n or dFunc) return coroutine.yield(CMD, t_hold, n or dFunc, nil, interval)
end end
end end
@ -1226,7 +1226,7 @@ function multi:attachScheduler()
if type(name) == "function" then if type(name) == "function" then
name = "Thread#"..threadCount name = "Thread#"..threadCount
end end
local c={} local c={nil,nil,nil,nil,nil,nil,nil}
local env = {self=c} local env = {self=c}
c.TempRets = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil} c.TempRets = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}
c.startArgs = {...} c.startArgs = {...}
@ -1332,34 +1332,6 @@ function multi:attachScheduler()
local t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15 local t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15
local r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16 local r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16
local ret,_ local ret,_
local function CheckRets(i)
if threads[i] and not(threads[i].isError) then
if not _ then
threads[i].isError = true
threads[i].TempRets[1] = ret
return
end
if ret or r1 or r2 or r3 or r4 or r5 or r6 or r7 or r8 or r9 or r10 or r11 or r12 or r13 or r14 or r15 or r16 then
threads[i].TempRets[1] = ret
threads[i].TempRets[2] = r1
threads[i].TempRets[3] = r2
threads[i].TempRets[4] = r3
threads[i].TempRets[5] = r4
threads[i].TempRets[6] = r5
threads[i].TempRets[7] = r6
threads[i].TempRets[8] = r7
threads[i].TempRets[9] = r8
threads[i].TempRets[10] = r9
threads[i].TempRets[11] = r10
threads[i].TempRets[12] = r11
threads[i].TempRets[13] = r12
threads[i].TempRets[14] = r13
threads[i].TempRets[15] = r14
threads[i].TempRets[16] = r15
threads[i].TempRets[17] = r16
end
end
end
local function holdconn(n) local function holdconn(n)
if type(ret[n])=="table" and ret[n].Type=='connector' then if type(ret[n])=="table" and ret[n].Type=='connector' then
local letsgo local letsgo
@ -1371,58 +1343,6 @@ function multi:attachScheduler()
end end
end end
end end
local function helper(CMD,arg1,arg2,arg3,arg4)
if type(ret)=="table" then
if ret[1]=="_kill_" then
threads[i].OnDeath:Fire(threads[i],"killed",ret,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16)
self.setType(threads[i],self.DestroyedObj)
table.remove(threads,i)
ret = nil
elseif ret[1]=="_sleep_" then
threads[i].sec = ret[2]
threads[i].time = clock()
threads[i].task = "sleep"
threads[i].__ready = false
ret = nil
elseif ret[1]=="_skip_" then
threads[i].count = ret[2]
threads[i].pos = 0
threads[i].task = "skip"
threads[i].__ready = false
ret = nil
elseif ret[1]=="_hold_" then
holdconn(2)
threads[i].func = ret[2]
threads[i].task = "hold"
threads[i].__ready = false
threads[i].interval = ret[4] or 0
threads[i].intervalR = clock()
ret = nil
elseif ret[1]=="_holdF_" then
holdconn(3)
threads[i].sec = ret[2]
threads[i].func = ret[3]
threads[i].task = "holdF"
threads[i].time = clock()
threads[i].__ready = false
threads[i].interval = ret[4] or 0
threads[i].intervalR = clock()
ret = nil
elseif ret[1]=="_holdW_" then
holdconn(3)
threads[i].count = ret[2]
threads[i].pos = 0
threads[i].func = ret[3]
threads[i].task = "holdW"
threads[i].time = clock()
threads[i].__ready = false
threads[i].interval = ret[4] or 0
threads[i].intervalR = clock()
ret = nil
end
end
CheckRets(i)
end
local task, thd, ref, ready local task, thd, ref, ready
--[[ --[[
if coroutine.running() ~= threads[i].thread then if coroutine.running() ~= threads[i].thread then
@ -1502,74 +1422,67 @@ function multi:attachScheduler()
} }
setmetatable(switch,{__index=function() return function() end end}) setmetatable(switch,{__index=function() return function() end end})
local cmds = {-- ipart: t_hold, t_sleep, t_holdF, t_skip, t_holdW, t_yield, t_none <-- Order local cmds = {-- ipart: t_hold, t_sleep, t_holdF, t_skip, t_holdW, t_yield, t_none <-- Order
-- function(th,arg1,arg2,arg3,arg4)
-- threads[i].OnDeath:Fire(threads[i],"killed",ret,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16)
-- self.setType(threads[i],self.DestroyedObj)
-- table.remove(threads,i)
-- ret = nil
-- end,
function(th,arg1,arg2,arg3,arg4) function(th,arg1,arg2,arg3,arg4)
threads[i].OnDeath:Fire(threads[i],"killed",ret,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16) th.func = arg1
self.setType(threads[i],self.DestroyedObj) th.task = t_hold
table.remove(threads,i) th.interval = arg4 or 0
ret = nil th.intervalR = clock()
end, end,
function(th,arg1,arg2,arg3,arg4) function(th,arg1,arg2,arg3,arg4)
print("SLEEP:",th,arg1,arg2,arg3,arg4)
th.sec = arg1 th.sec = arg1
th.time = clock() th.time = clock()
th.task = t_sleep th.task = t_sleep
ret = nil
end, end,
function(th,arg1,arg2,arg3,arg4) function(th,arg1,arg2,arg3,arg4)
threads[i].count = ret[2] th.sec = arg1
threads[i].pos = 0 th.func = arg2
threads[i].task = t_skip th.task = t_holdF
threads[i].__ready = false th.time = clock()
ret = nil th.interval = arg4 or 0
th.intervalR = clock()
end, end,
function(th,arg1,arg2,arg3,arg4) function(th,arg1,arg2,arg3,arg4)
holdconn(2) th.count = arg1
threads[i].func = ret[2] th.pos = 0
threads[i].task = t_hold th.task = t_skip
threads[i].__ready = false
threads[i].interval = ret[4] or 0
threads[i].intervalR = clock()
ret = nil
end, end,
function(th,arg1,arg2,arg3,arg4) function(th,arg1,arg2,arg3,arg4)
holdconn(3) th.count = arg1
threads[i].sec = ret[2] th.pos = 0
threads[i].func = ret[3] th.func = arg2
threads[i].task = t_holdF th.task = t_holdW
threads[i].time = clock() th.time = clock()
threads[i].__ready = false th.interval = arg4 or 0
threads[i].interval = ret[4] or 0 th.intervalR = clock()
threads[i].intervalR = clock()
ret = nil
end,
function(th,arg1,arg2,arg3,arg4)
holdconn(3)
threads[i].count = ret[2]
threads[i].pos = 0
threads[i].func = ret[3]
threads[i].task = t_holdW
threads[i].time = clock()
threads[i].__ready = false
threads[i].interval = ret[4] or 0
threads[i].intervalR = clock()
ret = nil
end, end,
function() end function() end
} }
setmetatable(cmds,{__index=function() return function() end end}) setmetatable(cmds,{__index=function() return function() end end})
local co_status = { local co_status = {
["suspended"] = function(thd,ref,task) ["suspended"] = function(thd,ref,task)
print(ref,r2,r3,r4,r5)
switch[task](ref,thd) switch[task](ref,thd)
--cmds[r1](ref,r2,r3,r4,r5) cmds[r1](ref,r2,r3,r4,r5)
if not _ then
print(ret,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16)
io.read() -- This is an error spot too
end
r1=nil r2=nil r3=nil r4=nil r5=nil
end, end,
["normal"] = function(thd,ref) end, -- Not sure if I will handle this ["normal"] = function(thd,ref) end, -- Not sure if I will handle this
["running"] = function(thd,ref) end, ["running"] = function(thd,ref) end,
["dead"] = function(thd,ref) ["dead"] = function(thd,ref,task,i)
local t = ref.TempRets or {} local t = ref.TempRets or {}
print(_,ref.Name,ret,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16)
print("ended",t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16])
ref.OnDeath:Fire(ref,"ended",t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16]) ref.OnDeath:Fire(ref,"ended",t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15],t[16])
self.setType(ref,self.DestroyedObj)
table.remove(threads,i) table.remove(threads,i)
self.setType(ref,self.DestroyedObj)
end, end,
} }
self.scheduler:OnLoop(function(self) self.scheduler:OnLoop(function(self)
@ -1581,10 +1494,10 @@ function multi:attachScheduler()
for start = 1, startme_len do for start = 1, startme_len do
_,ret,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16=resume(startme[start].thread,unpack(startme[start].startArgs)) _,ret,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16=resume(startme[start].thread,unpack(startme[start].startArgs))
cmds[r1](ref,r2,r3,r4,r5) -- An error can happen here
cmds[r1](startme[start],r2,r3,r4,r5)
startme_len = startme_len - 1 startme_len = startme_len - 1
end end
-- if threads[i].isError then -- if threads[i].isError then
-- if status(threads[i].thread)=="dead" then -- if status(threads[i].thread)=="dead" then
-- threads[i].OnError:Fire(threads[i],unpack(threads[i].TempRets)) -- threads[i].OnError:Fire(threads[i],unpack(threads[i].TempRets))
@ -1592,22 +1505,9 @@ function multi:attachScheduler()
-- table.remove(threads,i) -- table.remove(threads,i)
-- end -- end
-- end -- end
co_status[status(thd)](thd,ref,task) co_status[status(thd)](thd,ref,task,i)
if threads[i] and threads[i].__ready then
threads[i].__ready = false
if coroutine.running() ~= threads[i].thread then
CheckRets(i)
end
end
helper(i)
end end
end) end)
if justThreads then
while true do
self.scheduler:Act()
end
end
end end
end end

View File

@ -4,30 +4,34 @@ local multi,thread = require("multi"):init()
Before AVG: 522386 Before AVG: 522386
Test 1 AVG: Test 1 AVG:
]] ]]
local sleep_for = 5 local sleep_for = 100000
local conn = multi:newConnection()
local function bench(_,steps) local function bench(_,steps)
print("Steps/5s: "..steps) print("Steps/5s: "..steps)
os.exit() os.exit()
end end
local ready = false
multi:newAlarm(3):OnRing(function()
conn:Fire()
end)
multi:benchMark(sleep_for,multi.Priority_Core,"Core:"):OnBench(bench) multi:benchMark(sleep_for,multi.Priority_Core,"Core:"):OnBench(bench)
multi:newThread("Thread 1",function(a,b,c) multi:newThread("Thread 1",function()
print(a,b,c)
while true do while true do
print(1) thread.hold(conn) -- We just need to run things
thread.sleep(1) -- We just need to run things
print("1 ...")
end end
end,1,2,3) end)
multi:newThread("Thread 2",function(a,b,c) multi:newThread("Thread 2",function()
print(a,b,c) thread.sleep(1)
error("Hi")
end)
multi:newThread("Thread 3",function()
while true do while true do
print(2)
thread.sleep(1) -- We just need to run things thread.sleep(1) -- We just need to run things
print("2 ...") print("3 ...")
end end
end,4,5,6) end)
-- multi.OnExit(function() -- multi.OnExit(function()
-- print("Total: ".. a) -- print("Total: ".. a)