From 16b0354c425327eb7a29b263e470599d139e4e89 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Fri, 21 Feb 2020 13:22:41 -0500 Subject: [PATCH] Add utils.lua that contains the helper methods. Keeps the main file cleaner --- changes.md | 29 +- multi/init.lua | 600 ++------------------------------ multi/utils.lua | 339 ++++++++++++++++++ rockspecs/multi-14.2-0.rockspec | 35 ++ test.lua | 17 +- 5 files changed, 452 insertions(+), 568 deletions(-) create mode 100644 multi/utils.lua create mode 100644 rockspecs/multi-14.2-0.rockspec diff --git a/changes.md b/changes.md index ff476a2..c00e5ab 100644 --- a/changes.md +++ b/changes.md @@ -4,7 +4,7 @@ Table of contents --- [Update 14.1.0 - A whole new world of possibilities](#update-1410---a-whole-new-world-of-possibilities)
[Update 14.0.0 - Consistency, Additions and Stability](#update-1400-consistency-additions-and-stability)
[Update 13.1.0 - Bug fixes and features added](#update-1310-bug-fixes-and-features-added)
[Update 13.0.0 - Added some documentation, and some new features too check it out!](#update-1300-added-some-documentation-and-some-new-features-too-check-it-out)
[Update 12.2.2 - Time for some more bug fixes!](#update-1222-time-for-some-more-bug-fixes)
[Update 12.2.1 - Time for some bug fixes!](#update-1221-time-for-some-bug-fixes)
[Update 12.2.0 - The chains of binding](#update-1220---the-chains-of-binding)
[Update 12.1.0 - Threads just can't hold on anymore](#update-1210---threads-just-cant-hold-on-anymore)
[Update: 12.0.0 - Big update (Lots of additions some changes)](#update-1200-big-update-lots-of-additions-some-changes)
[Update: 1.11.1 - Small Clarification on Love](#update-1111---small-clarification-on-love)
[Update: 1.11.0](#update-1110)
[Update: 1.10.0](#update-1100)
[Update: 1.9.2](#update-192)
[Update: 1.9.1 - Threads can now argue](#update-191---threads-can-now-argue)
[Update: 1.9.0](#update-190)
[Update: 1.8.7](#update-187)
[Update: 1.8.6](#update-186)
[Update: 1.8.5](#update-185)
[Update: 1.8.4](#update-184)
[Update: 1.8.3 - Mainloop recieves some needed overhauling](#update-183---mainloop-recieves-some-needed-overhauling)
[Update: 1.8.2](#update-182)
[Update: 1.8.1](#update-181)
[Update: 1.7.6](#update-176)
[Update: 1.7.5](#update-175)
[Update: 1.7.4](#update-174)
[Update: 1.7.3](#update-173)
[Update: 1.7.2](#update-172)
[Update: 1.7.1 - Bug Fixes Only](#update-171---bug-fixes-only)
[Update: 1.7.0 - Threading the systems](#update-170---threading-the-systems)
[Update: 1.6.0](#update-160)
[Update: 1.5.0](#update-150)
[Update: 1.4.1 (4/10/2017) - First Public release of the library](#update-141-4102017---first-public-release-of-the-library)
[Update: 1.4.0 (3/20/2017)](#update-140-3202017)
[Update: 1.3.0 (1/29/2017)](#update-130-1292017)
[Update: 1.2.0 (12.31.2016)](#update-120-12312016)
[Update: 1.1.0](#update-110)
[Update: 1.0.0](#update-100)
[Update: 0.6.3](#update-063)
[Update: 0.6.2](#update-062)
[Update: 0.6.1-6](#update-061-6)
[Update: 0.5.1-6](#update-051-6)
[Update: 0.4.1](#update-041)
[Update: 0.3.0 - The update that started it all](#update-030---the-update-that-started-it-all)
[Update: EventManager 2.0.0](#update-eventmanager-200)
[Update: EventManager 1.2.0](#update-eventmanager-120)
[Update: EventManager 1.1.0](#update-eventmanager-110)
[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)
[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different) -# Update 14.2.0 - State Saving reworked! +# Update 14.2.0 - The great pruning Full Update Showcase --- ```lua @@ -45,9 +45,36 @@ Changed: --- - Revamped the job system - multi.Jobs:newJob() + Removed: --- - multi:newTrigger() — Connections do everything this thing could do and more. +- multi:newHyperThreadedProcess(name)* +- multi:newThreadedProcess(name)* +- multi.nextStep(func)* — The new job System can be used instead to achieve this +- multi.queuefinal(self) — An Old method for a feature long gone from the library +- multi:setLoad(n)* +- multi:setThrestimed(n)* +- multi:setDomainName(name)* +- multi:linkDomain(name)* +- multi:_Pause()* — Use multi:Stop() instead! +- multi:isHeld()/multi:IsHeld()* Holding is handled differently so a held variable is no longer needed for chacking. +- multi.executeFunction(name,...)* +- multi:getError()* — Errors are nolonger gotten like that, multi.OnError(func) is the way to go +- multi.startFPSMonitior()* +- multi.doFPS(s)* +- +- +- +- +- +- +- +- +- +- + +*Many features have become outdated/redundant with new features and additions that have been added to the library # Update 14.1.0 - A whole new world of possibilities Full Update Showcase --- diff --git a/multi/init.lua b/multi/init.lua index 621892e..e8922e5 100644 --- a/multi/init.lua +++ b/multi/init.lua @@ -22,13 +22,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] local multi = {} +local mainloopActive = false +local isRunning = false local clock = os.clock local thread = {} if not _G["$multi"] then _G["$multi"] = {multi=multi,thread=thread} end multi.Version = "14.2.0" -multi._VERSION = "14.2.0" multi.stage = "stable" multi.__index = multi multi.Name = "multi.root" @@ -37,7 +38,6 @@ multi.Garbage = {} multi.ender = {} multi.Children = {} multi.Active = true -multi.fps = 60 multi.Type = "mainprocess" multi.Rest = 0 multi._type = type @@ -46,28 +46,6 @@ multi.clock = os.clock multi.time = os.time multi.LinkedPath = multi multi.lastTime = clock() -multi.DestroyedObj = { - Type = "destroyed", -} -local function uni() - return multi.DestroyedObj -end - -setmetatable(multi.DestroyedObj, { - __index = function(t,k) - return setmetatable({},{__index = uni,__newindex = uni,__call = uni,__metatable = multi.DestroyedObj,__tostring = function() return "destroyed" end,__unm = uni,__add = uni,__sub = uni,__mul = uni,__div = uni,__mod = uni,__pow = uni,__concat = uni}) - end,__newindex = uni,__call = uni,__metatable = multi.DestroyedObj,__tostring = function() return "destroyed" end,__unm = uni,__add = uni,__sub = uni,__mul = uni,__div = uni,__mod = uni,__pow = uni,__concat = uni -}) -math.randomseed(os.time()) -local mainloopActive = false -local isRunning = false -local next -local ncount = 0 -multi.defaultSettings = { - priority = 0, - protect = false, -} - multi.Priority_Core = 1 multi.Priority_Very_High = 4 multi.Priority_High = 16 @@ -94,266 +72,18 @@ multi.PriorityTick=1 multi.Priority=multi.Priority_High multi.threshold=256 multi.threstimed=.001 - + function multi.init() multi.NIL = {Type="NIL"} return _G["$multi"].multi,_G["$multi"].thread end -function multi.queuefinal(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - if self.Parent.Mainloop[#self.Parent.Mainloop].Type=="alarm" then - self.Parent.Mainloop[#self.Parent.Mainloop]:Reset() - self.Parent.Mainloop[#self.Parent.Mainloop].Active=true - else - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end -if table.unpack and not unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -function multi:setThrestimed(n) - self.deltaTarget=n or .1 -end -function multi:enableLoadDetection() - if multi.maxSpd then return end - -- here we are going to run a quick benchMark solo - local temp = multi:newProcessor() - temp:Start() - local t = os.clock() - local stop = false - temp:benchMark(.01):OnBench(function(time,steps) - stop = steps - end) - while not stop do - temp:uManager() - end - temp:Destroy() - multi.maxSpd = stop -end -local MaxLoad = nil -function multi:setLoad(n) - MaxLoad = n -end -local busy = false -local lastVal = 0 -local bb = 0 -function multi:getLoad() - if not multi.maxSpd then multi:enableLoadDetection() end - if busy then return lastVal end - local val = nil - if thread.isThread() then - local bench - multi: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 - multi:benchMark(.01):OnBench(function(time,steps) - bench = steps - bb = steps - end) - while not bench do - multi:uManager() - end - bench = bench^1.5 - val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100) - busy = false - end - if val<0 then val = 0 end - if val > 100 then val = 100 end - lastVal = val - return val,bb*100 -end -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=="very high" or s:lower()=="vh" then - self.Priority=self.Priority_Very_High - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='a' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='b' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=="very low" or s:lower()=="vl" then - self.Priority=self.Priority_Very_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - self.solid = true - end - if not self.PrioritySet then - self.defPriority = self.Priority - self.PrioritySet = true - end -end -function multi:ResetPriority() - self.Priority = self.defPriority -end + -- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi.randomString(n) - local str = '' - local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} - for i=1,n do - str = str..''..strings[math.random(1,#strings)] - end - return str -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -multi.GetParentProcess=multi.getParentProcess function multi.Stop() mainloopActive=false end -function multi:isHeld() - return self.held -end -multi.important={} -multi.IsHeld=multi.isHeld -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - multi.print('Error: Not a function') - end -end -function multi:getChildren() - return self.Mainloop -end -function multi:getVersion() - return multi.Version -end -function multi:getPlatform() - if love then - if love.thread then - return "love2d" - end - else - return "lanes" - end -end -function multi:canSystemThread() - return false -end + --Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:benchMark(sec,p,pt) - local c = 0 - local temp=self:newLoop(function(self,t) - if t>sec then - if pt then - multi.print(pt.." "..c.." Steps in "..sec.." second(s)!") - end - self.tt(sec,c) - self:Destroy() - else - c=c+1 - end - end) - temp:setPriority(p or 1) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - return temp -end -function multi.Round(num, numDecimalPlaces) - local mult = 10^(numDecimalPlaces or 0) - return math.floor(num * mult + 0.5) / mult -end -function multi.AlignTable(tab) - local longest = {} - local columns = #tab[1] - local rows = #tab - for i=1, columns do - longest[i] = -math.huge - end - for i = 1,rows do - for j = 1,columns do - tab[i][j] = tostring(tab[i][j]) - if #tab[i][j]>longest[j] then - longest[j] = #tab[i][j] - end - end - end - for i = 1,rows do - for j = 1,columns do - if tab[i][j]~=nil and #tab[i][j]= "Lua 5.2" then - setmetatable(multi.m, {__gc = multi.m.onexit}) -else - multi.m.sentinel = newproxy(true) - getmetatable(multi.m.sentinel).__gc = multi.m.onexit -end + -- Threading stuff multi.GlobalVariables={} -if os.getOS()=="windows" then - thread.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) -else - thread.__CORES=tonumber(io.popen("nproc --all"):read("*n")) -end -thread.requests = {} local dFunc = function() return true end local dRef = {nil,nil,nil} function thread.request(t,cmd,...) @@ -1619,6 +1275,7 @@ function multi.initThreads(justThreads) if type(ret)=="table" then if ret[1]=="_kill_" then threads[i].OnDeath:Fire(threads[i],"killed",ret,r1,r2,r3,r4,r5,r6) + multi.setType(threads[i],multi.DestroyedObj) table.remove(threads,i) ret = nil elseif ret[1]=="_sleep_" then @@ -1670,6 +1327,7 @@ function multi.initThreads(justThreads) for i=#threads,1,-1 do if threads[i].isError then threads[i].OnError:Fire(threads[i],unpack(threads[i].TempRets)) + multi.setType(threads[i],multi.DestroyedObj) table.remove(threads,i) end if threads[i] and not threads[i].__started then @@ -1685,6 +1343,7 @@ function multi.initThreads(justThreads) end if threads[i] and coroutine.status(threads[i].thread)=="dead" then threads[i].OnDeath:Fire(threads[i],"ended",unpack(threads[i].TempRets or {})) + multi.setType(threads[i],multi.DestroyedObj) table.remove(threads,i) elseif threads[i] and threads[i].task == "skip" then threads[i].pos = threads[i].pos + 1 @@ -1749,7 +1408,6 @@ end function multi:threadloop() multi.initThreads(true) end -multi.OnError=multi:newConnection() function multi:newService(func) -- Priority managed threads local c = {} c.Type = "service" @@ -1778,11 +1436,16 @@ function multi:newService(func) -- Priority managed threads task(ap) return c end - multi:newThread(function() + local th = multi:newThread(function() while true do process() end - end).OnError = c.OnError -- use the threads onerror as our own + end) + th.OnError = c.OnError -- use the threads onerror as our own + function c.Destroy() + th:kill() + multi.setType(c,multi.DestroyedObj) + end function c:SetScheme(n) if type(self)=="number" then n = self end scheme = n @@ -1862,187 +1525,11 @@ multi.Jobs.OnStarted(function(self,jobs) end) multi.Jobs.SetPriority(multi.Priority_Normal) multi.Jobs.Start() -function multi:newThreadedProcess(name) - local c = {} - local holding = false - local kill = false - setmetatable(c, multi) - function c:newBase(ins) - local ct = {} - ct.Active=true - ct.func={} - ct.ender={} - ct.Act=function() end - ct.Parent=self - ct.held=false - ct.ref=self.ref - table.insert(self.Mainloop,ct) - return ct - end - c.Parent=self - c.Active=true - c.func={} - c.Type='threadedprocess' - c.Mainloop={} - c.Garbage={} - c.Children={} - c.Active=true - c.Rest=0 - c.updaterate=.01 - c.restRate=.1 - c.queue={} - c.rest=false - function c:getController() - return nil - end - function c:Start() - self.rest=false - return self - end - function c:Resume() - self.rest=false - return self - end - function c:Pause() - self.rest=true - return self - end - function c:Remove() - self.ref:kill() - return self - end - function c:Kill() - kill = true - return self - end - function c:Sleep(n) - holding = true - if type(n)=="number" then - multi:newAlarm(n):OnRing(function(a) - holding = false - a:Destroy() - end):setName("multi.TPSleep") - elseif type(n)=="function" then - multi:newEvent(n):OnEvent(function(e) - holding = false - e:Destroy() - end):setName("multi.TPHold") - end - return self - end - c.Hold=c.Sleep - multi:newThread(name,function(ref) - while true do - thread.hold(function() - return not(holding) - end) - c:uManager() - end - end) - multi:create(c) - return c -end -function multi:newHyperThreadedProcess(name) - if not name then error("All threads must have a name!") end - local c = {} - setmetatable(c, multi) - local ind = 0 - local holding = true - local kill = false - function c:newBase(ins) - local ct = {} - ct.Active=true - ct.func={} - ct.ender={} - ct.Act=function() end - ct.Parent=self - ct.held=false - ct.ref=self.ref - ind = ind + 1 - multi:newThread("Proc <"..name.."> #"..ind,function() - while true do - thread.hold(function() - return not(holding) - end) - if kill then - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - ct:Act() - end - end) - return ct - end - c.Parent=self - c.Active=true - c.func={} - c.Type='hyperthreadedprocess' - c.Mainloop={} - c.Garbage={} - c.Children={} - c.Active=true - c.Rest=0 - c.updaterate=.01 - c.restRate=.1 - c.queue={} - c.rest=false - function c:getController() - return nil - end - function c:Start() - holding = false - return self - end - function c:Resume() - holding = false - return self - end - function c:Pause() - holding = true - return self - end - function c:Remove() - self.ref:kill() - return self - end - function c:Kill() - kill = true - return self - end - function c:Sleep(b) - holding = true - if type(b)=="number" then - local t = os.clock() - multi:newAlarm(b):OnRing(function(a) - holding = false - a:Destroy() - end):setName("multi.HTPSleep") - elseif type(b)=="function" then - multi:newEvent(b):OnEvent(function(e) - holding = false - e:Destroy() - end):setName("multi.HTPHold") - end - return self - end - c.Hold=c.Sleep - multi:create(c) - return c -end -- Multi runners function multi:lightloop() if not isRunning then local Loop=self.Mainloop while true do - if next then - local DD = table.remove(next,1) - while DD do - DD() - DD = table.remove(next,1) - end - end for _D=#Loop,1,-1 do if Loop[_D].Active then self.CID=_D @@ -2100,13 +1587,6 @@ function multi:mainloop(settings) local cc=0 multi.OnLoad:Fire() while mainloopActive do - if next then - local DD = table.remove(next,1) - while DD do - DD() - DD = table.remove(next,1) - end - end if priority == 1 then for _D=#Loop,1,-1 do for P=1,7 do @@ -2300,13 +1780,6 @@ function multi:uManager(settings) end function multi:uManagerRef(settings) if self.Active then - if next then - local DD = table.remove(next,1) - while DD do - DD() - DD = table.remove(next,1) - end - end local Loop=self.Mainloop local PS=self if multi.defaultSettings.priority==1 then @@ -2464,4 +1937,5 @@ function multi:uManagerRef(settings) end end end +require("multi.utils").init(multi,thread) return multi diff --git a/multi/utils.lua b/multi/utils.lua new file mode 100644 index 0000000..da5da15 --- /dev/null +++ b/multi/utils.lua @@ -0,0 +1,339 @@ +function table.merge(t1, t2) + for k,v in pairs(t2) do + if type(v) == 'table' then + if type(t1[k] or false) == 'table' then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 +end +local function init(multi,thread) + if table.unpack and not unpack then + unpack=table.unpack + end + multi.DestroyedObj = { + Type = "destroyed", + } + + local function uni() + return multi.DestroyedObj + end + + local function uniN() end + function multi.setType(obj,t) + if t == multi.DestroyedObj then + for i,v in pairs(obj) do + obj[i] = nil + end + setmetatable(obj, { + __index = function(t,k) + return setmetatable({},{__index = uni,__newindex = uni,__call = uni,__metatable = multi.DestroyedObj,__tostring = function() return "destroyed" end,__unm = uni,__add = uni,__sub = uni,__mul = uni,__div = uni,__mod = uni,__pow = uni,__concat = uni}) + end,__newindex = uni,__call = uni,__metatable = multi.DestroyedObj,__tostring = function() return "destroyed" end,__unm = uni,__add = uni,__sub = uni,__mul = uni,__div = uni,__mod = uni,__pow = uni,__concat = uni + }) + end + end + setmetatable(multi.DestroyedObj, { + __index = function(t,k) + return setmetatable({},{__index = uni,__newindex = uni,__call = uni,__metatable = multi.DestroyedObj,__tostring = function() return "destroyed" end,__unm = uni,__add = uni,__sub = uni,__mul = uni,__div = uni,__mod = uni,__pow = uni,__concat = uni}) + end,__newindex = uni,__call = uni,__metatable = multi.DestroyedObj,__tostring = function() return "destroyed" end,__unm = uni,__add = uni,__sub = uni,__mul = uni,__div = uni,__mod = uni,__pow = uni,__concat = uni + }) + math.randomseed(os.time()) + multi.defaultSettings = { + priority = 0, + protect = false, + } + + function multi:enableLoadDetection() + if multi.maxSpd then return end + -- here we are going to run a quick benchMark solo + local temp = multi:newProcessor() + temp:Start() + local t = os.clock() + local stop = false + temp:benchMark(.01):OnBench(function(time,steps) + stop = steps + end) + while not stop do + temp:uManager() + end + temp:Destroy() + multi.maxSpd = stop + end + + local busy = false + local lastVal = 0 + local bb = 0 + + function multi:getLoad() + if not multi.maxSpd then multi:enableLoadDetection() end + if busy then return lastVal end + local val = nil + if thread.isThread() then + local bench + multi: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 + multi:benchMark(.01):OnBench(function(time,steps) + bench = steps + bb = steps + end) + while not bench do + multi:uManager() + end + bench = bench^1.5 + val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100) + busy = false + end + if val<0 then val = 0 end + if val > 100 then val = 100 end + lastVal = val + return val,bb*100 + end + + function multi:setPriority(s) + if type(s)==number then + self.Priority=s + elseif type(s)=='string' then + if s:lower()=='core' or s:lower()=='c' then + self.Priority=self.Priority_Core + elseif s:lower()=="very high" or s:lower()=="vh" then + self.Priority=self.Priority_Very_High + elseif s:lower()=='high' or s:lower()=='h' then + self.Priority=self.Priority_High + elseif s:lower()=='above' or s:lower()=='a' then + self.Priority=self.Priority_Above_Normal + elseif s:lower()=='normal' or s:lower()=='n' then + self.Priority=self.Priority_Normal + elseif s:lower()=='below' or s:lower()=='b' then + self.Priority=self.Priority_Below_Normal + elseif s:lower()=='low' or s:lower()=='l' then + self.Priority=self.Priority_Low + elseif s:lower()=="very low" or s:lower()=="vl" then + self.Priority=self.Priority_Very_Low + elseif s:lower()=='idle' or s:lower()=='i' then + self.Priority=self.Priority_Idle + end + self.solid = true + end + if not self.PrioritySet then + self.defPriority = self.Priority + self.PrioritySet = true + end + end + + function multi:ResetPriority() + self.Priority = self.defPriority + end + + function os.getOS() + if package.config:sub(1,1)=='\\' then + return 'windows' + else + return 'unix' + end + end + + if os.getOS()=='windows' then + function os.sleep(n) + if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end + end + else + function os.sleep(n) + os.execute('sleep ' .. tonumber(n)) + end + end + + function multi.randomString(n) + local str = '' + local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} + for i=1,n do + str = str..''..strings[math.random(1,#strings)] + end + return str + end + + function multi:getParentProcess() + return self.Mainloop[self.CID] + end + + function multi:getChildren() + return self.Mainloop + end + + function multi:getVersion() + return multi.Version + end + + function multi:getPlatform() + if love then + if love.thread then + return "love2d" + end + else + return "lanes" + end + end + + function multi:canSystemThread() + return false + end + + function multi:getError() + if self.error then + return self.error + end + end + + function multi:benchMark(sec,p,pt) + local c = 0 + local temp=self:newLoop(function(self,t) + if t>sec then + if pt then + multi.print(pt.." "..c.." Steps in "..sec.." second(s)!") + end + self.tt(sec,c) + self:Destroy() + else + c=c+1 + end + end) + temp:setPriority(p or 1) + function temp:OnBench(func) + self.tt=func + end + self.tt=function() end + return temp + end + + function multi.Round(num, numDecimalPlaces) + local mult = 10^(numDecimalPlaces or 0) + return math.floor(num * mult + 0.5) / mult + end + + function multi.AlignTable(tab) + local longest = {} + local columns = #tab[1] + local rows = #tab + for i=1, columns do + longest[i] = -math.huge + end + for i = 1,rows do + for j = 1,columns do + tab[i][j] = tostring(tab[i][j]) + if #tab[i][j]>longest[j] then + longest[j] = #tab[i][j] + end + end + end + for i = 1,rows do + for j = 1,columns do + if tab[i][j]~=nil and #tab[i][j]= "Lua 5.2" then + setmetatable(multi.m, {__gc = multi.m.onexit}) + else + multi.m.sentinel = newproxy(true) + getmetatable(multi.m.sentinel).__gc = multi.m.onexit + end +end +return {init=init} \ No newline at end of file diff --git a/rockspecs/multi-14.2-0.rockspec b/rockspecs/multi-14.2-0.rockspec new file mode 100644 index 0000000..fb261b9 --- /dev/null +++ b/rockspecs/multi-14.2-0.rockspec @@ -0,0 +1,35 @@ +package = "multi" +version = "14.2-0" +source = { + url = "git://github.com/rayaman/multi.git", + tag = "v14.2.0", +} +description = { + summary = "Lua Multi tasking library", + detailed = [[ + This library contains many methods for multi tasking. Features non coroutine based multitasking, coroutine based multi tasking, and system threading (Requires use of an integration). Check github for how to use. + ]], + homepage = "https://github.com/rayaman/multi", + license = "MIT" +} +dependencies = { + "lua >= 5.1", + "lanes", +} +build = { + type = "builtin", + modules = { + ["multi"] = "multi/init.lua", + ["multi.utils"] = "multi/utils.lua", + ["multi.compat.love2d"] = "multi/compat/love2d.lua", + ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", + ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", + ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", + ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", + ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", + ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", + ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", + --["multi.integration.networkManager"] = "multi/integration/networkManager.lua", + --["multi.integration.shared"] = "multi/integration/shared.lua" + } +} \ No newline at end of file diff --git a/test.lua b/test.lua index ddf36ce..b3fab45 100644 --- a/test.lua +++ b/test.lua @@ -1,10 +1,19 @@ package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path --local sterilizer = require("multi.integration.sterilization") local multi,thread = require("multi"):init() -bin = multi.DestroyedObj -local file = bin.new() -local data = file:getData() -print(data) +local test = multi:newThread(function() + while true do + thread.sleep(1) + print("Hello!") + end +end) +local alarm = multi:newAlarm(4):OnRing(function(a) + print(a.Type) + a:Destroy() + print(a.Type) + test:Destroy() +end) +multi:lightloop() -- function pushJobs() -- multi.Jobs:newJob(function() -- print("job called")