From 997ea48b54ca52c5be17ba9da307aec5f8f82ed0 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Sun, 9 Jan 2022 23:23:54 -0500 Subject: [PATCH] Writing tests, fixed some bugs with the library, testing luajit support --- .gitignore | 1 - changes.md | 12 ++--- jitpaths.lua | 2 + luapaths.lua | 1 + multi/init.lua | 115 +++++++++++++++--------------------------- test3.lua | 14 +++-- tests/objectTests.lua | 45 +++++++++++++++-- tests/runtests.lua | 20 ++++++-- 8 files changed, 119 insertions(+), 91 deletions(-) create mode 100644 jitpaths.lua create mode 100644 luapaths.lua diff --git a/.gitignore b/.gitignore index eebfe4d..3ca13af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - *.code-workspace *.dat test.lua diff --git a/changes.md b/changes.md index 7f654b1..a1566bc 100644 --- a/changes.md +++ b/changes.md @@ -26,6 +26,7 @@ Added: Changed: --- +- `multi.hold(n,opt)` now supports an option table like thread.hold does. - Connection Objects now pass on the parent object if created on a multiobj. This was to allow chaining to work properly with the new update ```lua @@ -73,15 +74,10 @@ Changed: - Fixed the getTaskDetails to handle the new format for threads -### Developer Note: - -Connections are one of the most complex objects that this library has outside of some of the system threaded stuff. I tend to add features to connection objects quite often. Just last update connections can be "added" together creating a temp connection that only triggers when all of the added connections got triggered as well. Thinking about the possibilities this could give developers using the library I had to changed the base classes to use connections. - -The best part about this is that connections allow for greater control over an object's events. You can add and remove events that have been connected to as well as a lot of other things. Reference the documentation [here](./Documentation.md#non-actor-connections) - - Removed: --- +- `multi:newFunction(func)` + - `thread:newFunction(func)` Has many more features and replaces completely what this function did - 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 @@ -89,6 +85,8 @@ 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 + ToDo: --- diff --git a/jitpaths.lua b/jitpaths.lua new file mode 100644 index 0000000..d513f01 --- /dev/null +++ b/jitpaths.lua @@ -0,0 +1,2 @@ +package.path = "./?/init.lua;C:/Luajit/lua/?.init.lua;C:/Luajit/lua/?.lua;" +package.cpath = "C:/Luajit/clib/?/core.dll;C:/Luajit/clib/?.dll;" \ No newline at end of file diff --git a/luapaths.lua b/luapaths.lua new file mode 100644 index 0000000..031ec1d --- /dev/null +++ b/luapaths.lua @@ -0,0 +1 @@ +package.path = "./?/init.lua;?.lua;".. package.path \ No newline at end of file diff --git a/multi/init.lua b/multi/init.lua index 8065d13..11753d0 100644 --- a/multi/init.lua +++ b/multi/init.lua @@ -114,7 +114,9 @@ function multi:getTasksDetails(t) name = " <"..name..">" end count = count + 1 - table.insert(str,{v.Type:sub(1,1):upper()..v.Type:sub(2,-1)..name,multi.Round(os.clock()-v.creationTime,3),self.PriorityResolve[v.Priority],v.TID}) + if not v.Type == "destroyed" then + table.insert(str,{v.Type:sub(1,1):upper()..v.Type:sub(2,-1)..name,multi.Round(os.clock()-v.creationTime,3),self.PriorityResolve[v.Priority],v.TID}) + end end if count == 0 then table.insert(str,{"Currently no processes running!","","",""}) @@ -202,9 +204,9 @@ local ignoreconn = true function multi:newConnection(protect,func,kill) local c={} local call_funcs = {} + local lock = false c.callback = func c.Parent=self - c.lock = false setmetatable(c,{__call=function(self,...) local t = ... if type(t)=="table" then @@ -246,7 +248,7 @@ function multi:newConnection(protect,func,kill) c.Type='connector' c.func={} c.ID=0 - c.protect=protect or false + local protect=protect or false local connections={} c.FC=0 function c:holdUT(n) @@ -274,16 +276,16 @@ function multi:newConnection(protect,func,kill) end end function c:Lock() - c.lock = true + lock = true return self end function c:Unlock() - c.lock = false + lock = false return self end - if c.protect then + if protect then function c:Fire(...) - if self.lock then return end + if lock then return end for i=#call_funcs,1,-1 do if not call_funcs[i] then return end pcall(call_funcs[i],...) @@ -303,6 +305,9 @@ function multi:newConnection(protect,func,kill) end end local fast = {} + function c:getConnections() + return call_funcs + end function c:fastMode() function self:Fire(...) for i=1,#fast do @@ -356,8 +361,8 @@ function multi:newConnection(protect,func,kill) end, }) function temp:Fire(...) - if self.Parent.lock then return end - if self.Parent.protect then + if lock then return end + if protect then local t=pcall(call_funcs,...) if t then return t @@ -635,17 +640,17 @@ end function multi:newEvent(task) local c=self:newBase() c.Type='event' - c.Task=task or function() end + local task = task or function() end function c:Act() - local t = {self.Task(self)} - if t[1] then + local t = task(self) + if t then self:Pause() self.returns = t c.OnEvent:Fire(self) end end function c:SetTask(func) - self.Task=func + task=func return self end c.OnEvent = self:newConnection() @@ -656,20 +661,20 @@ end function multi:newUpdater(skip) local c=self:newBase() c.Type='updater' - c.pos=1 - c.skip=skip or 1 + local pos = 1 + local skip = skip or 1 function c:Act() - if self.pos>=self.skip then - self.pos=0 + if pos >= skip then + pos = 0 self.OnUpdate:Fire(self) end - self.pos=self.pos+1 + pos = pos+1 end function c:SetSkip(n) - self.skip=n + skip=n return self end - c.OnUpdate=self:newConnection() + c.OnUpdate = self:newConnection() multi:create(c) return c end @@ -727,32 +732,6 @@ function multi:newLoop(func) multi:create(c) return c end -function multi:newFunction(func) - local c={} - c.func=func - c.Type = "mfunc" - mt={ - __index=multi, - __call=function(self,...) - if self.Active then - return self:func(...) - end - return nil,true - end - } - c.Parent=self - function c:Pause() - self.Active=false - return self - end - function c:Resume() - self.Active=true - return self - end - setmetatable(c,mt) - multi:create(c) - return c -end function multi:newStep(start,reset,count,skip) local c=self:newBase() @@ -1100,10 +1079,10 @@ function thread.waitFor(name) thread.hold(function() return thread.get(name)~=nil end) return thread.get(name) end -function multi.hold(func,no) - if thread.isThread() and not(no) then +function multi.hold(func,opt) + if thread.isThread() then if type(func) == "function" or type(func) == "table" then - return thread.hold(func) + return thread.hold(func,opt) end return thread.sleep(func) end @@ -1119,7 +1098,7 @@ function multi.hold(func,no) else local rets self:newThread("Hold_func",function() - rets = {thread.hold(func)} + rets = {thread.hold(func,opt)} death = true end) while not death do @@ -2166,31 +2145,19 @@ function multi:getLoad() if not multi.maxSpd then self:enableLoadDetection() end if busy then return lastVal,last_step end local val = nil - if thread.isThread() then - local bench - self:benchMark(.01):OnBench(function(time,steps) - bench = steps - bb = steps - end) - thread.hold(function() - return bench - end) - bench = bench^1.5 - val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100) - else - busy = true - local bench - self:benchMark(.01):OnBench(function(time,steps) - bench = steps - bb = steps - end) - while not bench do - self:uManager() - end - bench = bench^1.5 - val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100) - busy = false + local bench + self:benchMark(.01):OnBench(function(time,steps) + bench = steps + bb = steps + end) + _,timeout = multi.hold(function() + return bench + end,{sleep=.011}) + if timeout then + bench = 150000 end + bench = bench^1.5 + val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100) if val<0 then val = 0 end if val > 100 then val = 100 end lastVal = val diff --git a/test3.lua b/test3.lua index 4118ce6..5c74bdc 100644 --- a/test3.lua +++ b/test3.lua @@ -1,6 +1,8 @@ -package.path = "./?/init.lua;"..package.path +package.path = "./?.lua" +--require("jitpaths") +require("luapaths") local multi,thread = require("multi"):init() -local GLOBAL,THREAD = require("multi.integration.lanesManager"):init() +--local GLOBAL,THREAD = require("multi.integration.lanesManager"):init() -- func = THREAD:newFunction(function(a,b,c) -- print("Hello Thread!",a,b,c) @@ -22,7 +24,13 @@ local GLOBAL,THREAD = require("multi.integration.lanesManager"):init() -- end) multi:benchMark(1):OnBench(function(sec,steps) print("Steps:",steps) - os.exit() + --os.exit() +end) + +multi:newThread(function() + print(thread.hold(function() + return false + end,{sleep=1})) end) multi:mainloop() \ No newline at end of file diff --git a/tests/objectTests.lua b/tests/objectTests.lua index 9296a48..afb090b 100644 --- a/tests/objectTests.lua +++ b/tests/objectTests.lua @@ -1,3 +1,42 @@ -return function objectTests(multi,thread) - print("Testing Alarms!") -end \ No newline at end of file +function objectTests(multi,thread) + local alarms,tsteps,steps,loops,tloops,updaters,events=false,0,0,0,0,0,false + print("Testing Basic Features. If this fails most other features will probably not work!") + multi:newAlarm(2):OnRing(function(a) + alarms = true + a:Destroy() + end) + multi:newTStep(1,10,1,.1):OnStep(function(t) + tsteps = tsteps + 1 + end):OnEnd(function(step) + step:Destroy() + end) + multi:newStep(1,10):OnStep(function(s) + steps = steps + 1 + end):OnEnd(function(step) + step:Destroy() + end) + local loop = multi:newLoop(function(l) + loops = loops + 1 + end) + multi:newTLoop(function(t) + tloops = tloops + 1 + end,.1) + local updater = multi:newUpdater(1):OnUpdate(function() + updaters = updaters + 1 + end) + local event = multi:newEvent(function() + return alarms + end) + event.OnEvent(function(evnt) + events = true + print("Alarms: Ok") + print("Events: Ok") + if tsteps == 10 then print("TSteps: Ok") else print("TSteps: Bad!") end + if steps == 10 then print("Steps: Ok") else print("Steps: Bad!") end + if loops > 100 then print("Loops: Ok") else print("Loops: Bad!") end + 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 +end +return objectTests \ No newline at end of file diff --git a/tests/runtests.lua b/tests/runtests.lua index e0faa88..d9f4d0c 100644 --- a/tests/runtests.lua +++ b/tests/runtests.lua @@ -16,6 +16,20 @@ package.path="../?.lua;../?/init.lua;../?.lua;../?/?/init.lua;"..package.path This will be pushed directly to the master as tests start existing. ]] local multi, thread = require("multi"):init() -function runTest(path) - -end \ No newline at end of file + +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") + os.exit() +end,true) +print(runTest()) +multi:mainloop() \ No newline at end of file