Fix some bugs, added connection/thread tests
This commit is contained in:
parent
b8b31253d4
commit
4877f64ca1
@ -66,7 +66,7 @@ Changed:
|
||||
|
||||
- Connection Objects no longer Fire with syntax sugar when attached to an object:
|
||||
|
||||
`multiobj:OnSomeEvent(arg1,arg2.arg3)` No longer triggers the Fire event. As part of the update to make all objects use connections internally this little used feature had to be scrapped!
|
||||
`multiobj:OnSomeEvent(...)` No longer triggers the Fire event. As part of the update to make all objects use connections internally this little used feature had to be scrapped!
|
||||
|
||||
- multi:newTStep now derives it's functionality from multi:newStep (Cut's down on code length a bit)
|
||||
|
||||
@ -76,14 +76,16 @@ Removed:
|
||||
---
|
||||
- `multi:newFunction(func)`
|
||||
- `thread:newFunction(func)` Has many more features and replaces what multi:newFunction did
|
||||
- `multi.holdFor()` Now that multi.hold takes the option table that thread.hold has this feature can be emulated using that.
|
||||
|
||||
- Calling Fire on a connection no longer returns anything! Now that internal features use connections, I noticed how slow connections are and have increased their speed quite a bit. From 50,000 Steps per seconds to almost 7 Million. All other features should work just fine. Only returning values has been removed
|
||||
|
||||
Fixed:
|
||||
---
|
||||
- [Issue](https://github.com/rayaman/multi/issues/30) with Lanes crashing the lua state. Issue seems to be related to my filesystem
|
||||
- [Issue](https://github.com/rayaman/multi/issues/29) where System threaded functions not up to date with threaded functions
|
||||
- Issue where gettasksdetails would try to process a destroyed object causing it to crash
|
||||
- [Issue](https://github.com/rayaman/multi/issues/29) where System threaded functions not being up to date with threaded functions
|
||||
- Issue where gettasksdetails() would try to process a destroyed object causing it to crash
|
||||
- Issue with multi.hold() not pumping the mainloop and only the scheduler
|
||||
|
||||
|
||||
ToDo:
|
||||
|
||||
176
multi/init.lua
176
multi/init.lua
@ -137,7 +137,7 @@ function multi:getTasksDetails(t)
|
||||
{"Thread Name","Uptime","TID","Attached To"}
|
||||
}
|
||||
local proc_tab = {
|
||||
{"Process Name", "Uptime", "PID", "Load", "Cycles per Second per task"}
|
||||
{"Process Name", "Uptime", "PID", "Load", "CpS"}
|
||||
}
|
||||
for th,process in pairs(globalThreads) do
|
||||
if tostring(th.isProcessThread) == "destroyed" then
|
||||
@ -372,7 +372,7 @@ function multi:newConnection(protect,func,kill)
|
||||
end
|
||||
end
|
||||
function temp:Destroy()
|
||||
for i=1,#call_funcs do
|
||||
for i=#call_funcs,1,-1 do
|
||||
if call_funcs[i]~=nil then
|
||||
if call_funcs[i]==self.func then
|
||||
table.remove(call_funcs,i)
|
||||
@ -742,8 +742,6 @@ function multi:newStep(start,reset,count,skip)
|
||||
c.skip=skip or 0
|
||||
c.spos=0
|
||||
c.count=count or 1*think
|
||||
c.funcE={}
|
||||
c.funcS={}
|
||||
c.start=start or 1
|
||||
if start~=nil and reset~=nil then
|
||||
if start>reset then
|
||||
@ -905,9 +903,13 @@ function multi:scheduleJob(time,func)
|
||||
end
|
||||
|
||||
local __CurrentProcess = multi
|
||||
local __CurrentTask
|
||||
function multi.getCurrentProcess()
|
||||
return __CurrentProcess
|
||||
end
|
||||
function multi.getCurrentTask()
|
||||
return __CurrentTask
|
||||
end
|
||||
|
||||
local sandcount = 1
|
||||
function multi:newProcessor(name)
|
||||
@ -1087,14 +1089,17 @@ function multi.hold(func,opt)
|
||||
return thread.sleep(func)
|
||||
end
|
||||
local death = false
|
||||
local proc = multi.getCurrentTask()
|
||||
proc:Pause()
|
||||
if type(func)=="number" then
|
||||
self:newThread("Hold_func",function()
|
||||
thread.sleep(func)
|
||||
thread.hold(func)
|
||||
death = true
|
||||
end)
|
||||
while not death do
|
||||
multi.scheduler:Act()
|
||||
multi:uManager()
|
||||
end
|
||||
proc:Resume()
|
||||
else
|
||||
local rets
|
||||
self:newThread("Hold_func",function()
|
||||
@ -1102,25 +1107,13 @@ function multi.hold(func,opt)
|
||||
death = true
|
||||
end)
|
||||
while not death do
|
||||
multi.scheduler:Act()
|
||||
multi:uManager()
|
||||
end
|
||||
proc:Resume()
|
||||
return unpack(rets)
|
||||
end
|
||||
end
|
||||
function multi.holdFor(n,func)
|
||||
local temp
|
||||
multi.getCurrentProcess():newThread(function()
|
||||
thread.sleep(n)
|
||||
temp = true
|
||||
end)
|
||||
return multi.getCurrentProcess().hold(function()
|
||||
if func() then
|
||||
return func()
|
||||
elseif temp then
|
||||
return multi.NIL, multi.TIMEOUT
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function cleanReturns(...)
|
||||
local returns = {...}
|
||||
local rets = {}
|
||||
@ -1133,10 +1126,12 @@ local function cleanReturns(...)
|
||||
end
|
||||
return unpack(returns,1,ind)
|
||||
end
|
||||
|
||||
function thread.pushStatus(...)
|
||||
local t = thread.getRunningThread()
|
||||
t.statusconnector:Fire(...)
|
||||
end
|
||||
|
||||
function thread:newFunctionBase(generator,holdme)
|
||||
return function()
|
||||
local tfunc = {}
|
||||
@ -1635,12 +1630,14 @@ function multi:lightloop(settings)
|
||||
multi.OnPreLoad:Fire()
|
||||
if not isRunning then
|
||||
local Loop=self.Mainloop
|
||||
local ctask
|
||||
while true do
|
||||
for _D=#Loop,1,-1 do
|
||||
if Loop[_D].Active then
|
||||
self.CID=_D
|
||||
__CurrentTask = Loop[_D]
|
||||
ctask = __CurrentTask
|
||||
if ctask.Active then
|
||||
if not protect then
|
||||
Loop[_D]:Act()
|
||||
ctask:Act()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1692,26 +1689,29 @@ function multi:mainloop(settings)
|
||||
local autoP = 0
|
||||
local solid,sRef
|
||||
local cc=0
|
||||
local ctask
|
||||
multi.OnLoad:Fire()
|
||||
while mainloopActive do
|
||||
if priority == 1 then
|
||||
for _D=#Loop,1,-1 do
|
||||
__CurrentTask = Loop[_D]
|
||||
ctask = __CurrentTask
|
||||
for P=1,7 do
|
||||
if Loop[_D] then
|
||||
if (PS.PList[P])%Loop[_D].Priority==0 then
|
||||
if Loop[_D].Active then
|
||||
if ctask then
|
||||
if (PS.PList[P])%ctask.Priority == 0 then
|
||||
if ctask.Active then
|
||||
self.CID = _D
|
||||
if not protect then
|
||||
Loop[_D]:Act()
|
||||
ctask:Act()
|
||||
__CurrentProcess = self
|
||||
else
|
||||
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
||||
local status, err = pcall(ctask.Act,ctask)
|
||||
__CurrentProcess = self
|
||||
if err then
|
||||
Loop[_D].error=err
|
||||
self.OnError:Fire(Loop[_D],err)
|
||||
ctask.error=err
|
||||
self.OnError:Fire(ctask,err)
|
||||
if stopOnError then
|
||||
Loop[_D]:Destroy()
|
||||
ctask:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1722,21 +1722,22 @@ function multi:mainloop(settings)
|
||||
end
|
||||
elseif priority == 2 then
|
||||
for _D=#Loop,1,-1 do
|
||||
if Loop[_D] then
|
||||
if (PStep)%Loop[_D].Priority==0 then
|
||||
if Loop[_D].Active then
|
||||
self.CID=_D
|
||||
__CurrentTask = Loop[_D]
|
||||
ctask = __CurrentTask
|
||||
if ctask then
|
||||
if (PStep)%ctask.Priority==0 then
|
||||
if ctask.Active then
|
||||
if not protect then
|
||||
Loop[_D]:Act()
|
||||
ctask:Act()
|
||||
__CurrentProcess = self
|
||||
else
|
||||
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
||||
local status, err=pcall(ctask.Act,ctask)
|
||||
__CurrentProcess = self
|
||||
if err then
|
||||
Loop[_D].error=err
|
||||
self.OnError:Fire(Loop[_D],err)
|
||||
ctask.error=err
|
||||
self.OnError:Fire(ctask,err)
|
||||
if stopOnError then
|
||||
Loop[_D]:Destroy()
|
||||
ctask:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1756,21 +1757,22 @@ function multi:mainloop(settings)
|
||||
cc=0
|
||||
end
|
||||
for _D=#Loop,1,-1 do
|
||||
if Loop[_D] then
|
||||
if Loop[_D].Priority == p_c or (Loop[_D].Priority == p_h and tt<.5) or (Loop[_D].Priority == p_an and tt<.125) or (Loop[_D].Priority == p_n and tt<.063) or (Loop[_D].Priority == p_bn and tt<.016) or (Loop[_D].Priority == p_l and tt<.003) or (Loop[_D].Priority == p_i and tt<.001) then
|
||||
if Loop[_D].Active then
|
||||
self.CID=_D
|
||||
__CurrentTask = Loop[_D]
|
||||
ctask = __CurrentTask
|
||||
if ctask then
|
||||
if ctask.Priority == p_c or (ctask.Priority == p_h and tt<.5) or (ctask.Priority == p_an and tt<.125) or (ctask.Priority == p_n and tt<.063) or (ctask.Priority == p_bn and tt<.016) or (ctask.Priority == p_l and tt<.003) or (ctask.Priority == p_i and tt<.001) then
|
||||
if ctask.Active then
|
||||
if not protect then
|
||||
Loop[_D]:Act()
|
||||
ctask:Act()
|
||||
__CurrentProcess = self
|
||||
else
|
||||
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
||||
local status, err=pcall(ctask.Act,ctask)
|
||||
__CurrentProcess = self
|
||||
if err then
|
||||
Loop[_D].error=err
|
||||
self.OnError:Fire(Loop[_D],err)
|
||||
ctask.error=err
|
||||
self.OnError:Fire(ctask,err)
|
||||
if stopOnError then
|
||||
Loop[_D]:Destroy()
|
||||
ctask:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1780,51 +1782,51 @@ function multi:mainloop(settings)
|
||||
end
|
||||
elseif priority == -1 then
|
||||
for _D=#Loop,1,-1 do
|
||||
sRef = Loop[_D]
|
||||
if Loop[_D] then
|
||||
if (sRef.Priority == p_c) or PStep==0 then
|
||||
if sRef.Active then
|
||||
self.CID=_D
|
||||
__CurrentTask = Loop[_D]
|
||||
ctask = __CurrentTask
|
||||
if ctask then
|
||||
if (ctask.Priority == p_c) or PStep==0 then
|
||||
if ctask.Active then
|
||||
if not protect then
|
||||
if sRef.solid then
|
||||
sRef:Act()
|
||||
if ctask.solid then
|
||||
ctask:Act()
|
||||
__CurrentProcess = self
|
||||
solid = true
|
||||
else
|
||||
time = multi.timer(sRef.Act,sRef)
|
||||
sRef.solid = true
|
||||
time = multi.timer(ctask.Act,ctask)
|
||||
ctask.solid = true
|
||||
solid = false
|
||||
end
|
||||
if Loop[_D] and not solid then
|
||||
if ctask and not solid then
|
||||
if time == 0 then
|
||||
Loop[_D].Priority = p_c
|
||||
ctask.Priority = p_c
|
||||
else
|
||||
Loop[_D].Priority = P_LB
|
||||
ctask.Priority = P_LB
|
||||
end
|
||||
end
|
||||
else
|
||||
if Loop[_D].solid then
|
||||
Loop[_D]:Act()
|
||||
if ctask.solid then
|
||||
ctask:Act()
|
||||
__CurrentProcess = self
|
||||
solid = true
|
||||
else
|
||||
time, status, err=multi.timer(pcall,Loop[_D].Act,Loop[_D])
|
||||
time, status, err=multi.timer(pcall,ctask.Act,ctask)
|
||||
__CurrentProcess = self
|
||||
Loop[_D].solid = true
|
||||
ctask.solid = true
|
||||
solid = false
|
||||
end
|
||||
if Loop[_D] and not solid then
|
||||
if ctask and not solid then
|
||||
if time == 0 then
|
||||
Loop[_D].Priority = p_c
|
||||
ctask.Priority = p_c
|
||||
else
|
||||
Loop[_D].Priority = P_LB
|
||||
ctask.Priority = P_LB
|
||||
end
|
||||
end
|
||||
if err then
|
||||
Loop[_D].error=err
|
||||
self.OnError:Fire(Loop[_D],err)
|
||||
ctask.error=err
|
||||
self.OnError:Fire(ctask,err)
|
||||
if stopOnError then
|
||||
Loop[_D]:Destroy()
|
||||
ctask:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1844,20 +1846,21 @@ function multi:mainloop(settings)
|
||||
end
|
||||
else
|
||||
for _D=#Loop,1,-1 do
|
||||
if Loop[_D] then
|
||||
if Loop[_D].Active then
|
||||
self.CID=_D
|
||||
__CurrentTask = Loop[_D]
|
||||
ctask = __CurrentTask
|
||||
if ctask then
|
||||
if ctask.Active then
|
||||
if not protect then
|
||||
Loop[_D]:Act()
|
||||
ctask:Act()
|
||||
__CurrentProcess = self
|
||||
else
|
||||
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
||||
local status, err=pcall(ctask.Act,ctask)
|
||||
__CurrentProcess = self
|
||||
if err then
|
||||
Loop[_D].error=err
|
||||
self.OnError:Fire(Loop[_D],err)
|
||||
ctask.error=err
|
||||
self.OnError:Fire(ctask,err)
|
||||
if stopOnError then
|
||||
Loop[_D]:Destroy()
|
||||
ctask:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -2136,25 +2139,24 @@ function multi:enableLoadDetection()
|
||||
multi.maxSpd = stop
|
||||
end
|
||||
|
||||
local busy = false
|
||||
local lastVal = 0
|
||||
local last_step = 0
|
||||
local bb = 0
|
||||
|
||||
function multi:getLoad()
|
||||
if not multi.maxSpd then self:enableLoadDetection() end
|
||||
if busy then return lastVal,last_step end
|
||||
if not multi.maxSpd then multi:enableLoadDetection() end
|
||||
local val = nil
|
||||
local bench
|
||||
self:benchMark(.01):OnBench(function(time,steps)
|
||||
local bb
|
||||
self:benchMark(.01).OnBench(function(time,steps)
|
||||
bench = steps
|
||||
bb = steps
|
||||
end)
|
||||
_,timeout = multi.hold(function()
|
||||
return bench
|
||||
end,{sleep=.011})
|
||||
end,{sleep=.012})
|
||||
if timeout then
|
||||
bench = 150000
|
||||
bench = 0
|
||||
bb = 0
|
||||
end
|
||||
bench = bench^1.5
|
||||
val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100)
|
||||
|
||||
71
tests/connectionTest.lua
Normal file
71
tests/connectionTest.lua
Normal file
@ -0,0 +1,71 @@
|
||||
function connectionThreadTests(multi,thread)
|
||||
print("Starting Connection and Thread tests!")
|
||||
func = thread:newFunction(function(count)
|
||||
local a = 0
|
||||
while true do
|
||||
a = a + 1
|
||||
thread.sleep(.1)
|
||||
thread.pushStatus(a,count)
|
||||
if a == count then break end
|
||||
end
|
||||
return "Done"
|
||||
end)
|
||||
local ret = func(10)
|
||||
local ret2 = func(15)
|
||||
local ret3 = func(20)
|
||||
local s1,s2,s3 = 0,0,0
|
||||
ret.OnStatus(function(part,whole)
|
||||
s1 = math.ceil((part/whole)*1000)/10
|
||||
end)
|
||||
ret2.OnStatus(function(part,whole)
|
||||
s2 = math.ceil((part/whole)*1000)/10
|
||||
end)
|
||||
ret3.OnStatus(function(part,whole)
|
||||
s3 = math.ceil((part/whole)*1000)/10
|
||||
end)
|
||||
local err, timeout = thread.hold(ret2.OnReturn + ret.OnReturn + ret3.OnReturn,{sleep=3})
|
||||
if s1 == 100 and s2 == 100 and s3 == 100 then
|
||||
print("Threads: Ok")
|
||||
else
|
||||
print("Threads on status error")
|
||||
end
|
||||
if timeout then
|
||||
print("Threads or Connection error!")
|
||||
else
|
||||
print("Connection Test 1: Ok")
|
||||
end
|
||||
conn1 = multi:newConnection()
|
||||
conn2 = multi:newConnection()
|
||||
conn3 = multi:newConnection()
|
||||
local c1,c2,c3,c4 = false,false,false,false
|
||||
local a = conn1(function()
|
||||
c1 = true
|
||||
end)
|
||||
local b = conn2(function()
|
||||
c2 = true
|
||||
end)
|
||||
local c = conn3(function()
|
||||
c3 = true
|
||||
end)
|
||||
local d = conn3(function()
|
||||
c4 = true
|
||||
end)
|
||||
conn1:Fire()
|
||||
conn2:Fire()
|
||||
conn3:Fire()
|
||||
if c1 and c2 and c3 and c4 then
|
||||
print("Connection Test 2: Ok")
|
||||
else
|
||||
print("Connection Test 2: Error")
|
||||
end
|
||||
c3 = false
|
||||
c4 = false
|
||||
d:Destroy()
|
||||
conn3:Fire()
|
||||
if c3 and not(c4) then
|
||||
print("Connection Test 3: Ok")
|
||||
else
|
||||
print("Connection Test 3: Error removing connection")
|
||||
end
|
||||
end
|
||||
return connectionThreadTests
|
||||
@ -37,6 +37,6 @@ function objectTests(multi,thread)
|
||||
if tloops > 10 then print("TLoops: Ok") else print("TLoops: Bad!") end
|
||||
if updaters > 100 then print("Updaters: Ok") else print("Updaters: Bad!") end
|
||||
end)
|
||||
return event
|
||||
thread.hold(event.OnEvent)
|
||||
end
|
||||
return objectTests
|
||||
@ -16,20 +16,18 @@ package.path="./?.lua;../?.lua;../?/init.lua;../?.lua;../?/?/init.lua;"..package
|
||||
This will be pushed directly to the master as tests start existing.
|
||||
]]
|
||||
local multi, thread = require("multi"):init()
|
||||
|
||||
local good = false
|
||||
runTest = thread:newFunction(function()
|
||||
local objects = multi:newProcessor("Basic Object Tests")
|
||||
objects.Start()
|
||||
otest = require("tests/objectTests")(objects,thread)
|
||||
thread.hold(otest.OnEvent)
|
||||
print("Timers: Ok")
|
||||
print("Connections: Ok")
|
||||
print("Threads: Ok")
|
||||
print(objects:getTasksDetails())
|
||||
good = true
|
||||
print("\nTests done")
|
||||
require("tests/objectTests")(objects,thread)
|
||||
objects.Stop()
|
||||
local conn_thread = multi:newProcessor("Connection/Thread Tests")
|
||||
conn_thread.Start()
|
||||
require("tests/connectionTest")(conn_thread,thread)
|
||||
conn_thread.Stop()
|
||||
print(multi:getTasksDetails())
|
||||
os.exit()
|
||||
end,true)
|
||||
print(runTest())
|
||||
end)
|
||||
runTest()
|
||||
multi:mainloop()
|
||||
Loading…
x
Reference in New Issue
Block a user