mirror of
https://github.com/rayaman/multi.git
synced 2026-09-05 07:27:35 -04:00
1.9.2 is out!
Added, updated, and fixed stuff
This commit is contained in:
+290
-98
@@ -22,6 +22,62 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]
|
||||
require("bin")
|
||||
multi = {}
|
||||
multi.Version = "1.9.2"
|
||||
multi._VERSION = "1.9.2"
|
||||
multi.stage = "mostly-stable"
|
||||
multi.__index = multi
|
||||
multi.Mainloop = {}
|
||||
multi.Tasks = {}
|
||||
multi.Tasks2 = {}
|
||||
multi.Garbage = {}
|
||||
multi.ender = {}
|
||||
multi.Children = {}
|
||||
multi.Paused = {}
|
||||
multi.Active = true
|
||||
multi.fps = 60
|
||||
multi.Id = -1
|
||||
multi.Type = "mainprocess"
|
||||
multi.Rest = 0
|
||||
multi._type = type
|
||||
multi.Jobs = {}
|
||||
multi.queue = {}
|
||||
multi.jobUS = 2
|
||||
multi.clock = os.clock
|
||||
multi.time = os.time
|
||||
multi.LinkedPath = multi
|
||||
multi.isRunning = false
|
||||
--Do not change these ever...Any other number will not work (Unless you are using enablePriority2())
|
||||
multi.Priority_Core = 1
|
||||
multi.Priority_High = 4
|
||||
multi.Priority_Above_Normal = 16
|
||||
multi.Priority_Normal = 64
|
||||
multi.Priority_Below_Normal = 256
|
||||
multi.Priority_Low = 1024
|
||||
multi.Priority_Idle = 4096
|
||||
multi.PStep = 1
|
||||
multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle}
|
||||
--^^^^
|
||||
multi.PriorityTick=1 -- Between 1, 2 and 4
|
||||
multi.Priority=multi.Priority_Core
|
||||
multi.threshold=256
|
||||
multi.threstimed=.001
|
||||
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 then
|
||||
unpack=table.unpack
|
||||
end
|
||||
@@ -45,83 +101,19 @@ function print(...)
|
||||
_print(...)
|
||||
end
|
||||
end
|
||||
multi = {}
|
||||
multi.Version="1.9.1"
|
||||
multi._VERSION="1.9.1"
|
||||
multi.stage='mostly-stable'
|
||||
multi.__index = multi
|
||||
multi.Mainloop={}
|
||||
multi.Tasks={}
|
||||
multi.Tasks2={}
|
||||
multi.Garbage={}
|
||||
multi.ender={}
|
||||
multi.Children={}
|
||||
multi.Paused={}
|
||||
multi.Active=true
|
||||
multi.fps=60
|
||||
multi.Id=-1
|
||||
multi.Type='mainprocess'
|
||||
multi.Rest=0
|
||||
multi._type=type
|
||||
multi.Jobs={}
|
||||
multi.queue={}
|
||||
multi.jobUS=2
|
||||
multi.clock=os.clock
|
||||
multi.time=os.time
|
||||
multi.LinkedPath=multi
|
||||
multi.isRunning=false
|
||||
multi.queuefinal=function(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()
|
||||
_write=io.write
|
||||
function io.write(...)
|
||||
if not __SUPPRESSWRITES then
|
||||
_write(...)
|
||||
end
|
||||
end
|
||||
--Do not change these ever...Any other number will not work (Unless you are using enablePriority2())
|
||||
multi.Priority_Core=1
|
||||
multi.Priority_High=4
|
||||
multi.Priority_Above_Normal=16
|
||||
multi.Priority_Normal=64
|
||||
multi.Priority_Below_Normal=256
|
||||
multi.Priority_Low=1024
|
||||
multi.Priority_Idle=4096
|
||||
multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle}
|
||||
multi.PStep=1
|
||||
--^^^^
|
||||
multi.PriorityTick=1 -- Between 1,2 and 4
|
||||
multi.Priority=multi.Priority_Core
|
||||
multi.threshold=256
|
||||
multi.threstimed=.001
|
||||
function multi:setThreshold(n)
|
||||
self.threshold=n or 120
|
||||
end
|
||||
function multi:setThrestimed(n)
|
||||
self.threstimed=n or .001
|
||||
self.deltaTarget=n or .1
|
||||
end
|
||||
function multi:getLoad()
|
||||
return multi:newFunction(function(self)
|
||||
multi.scheduler:Pause()
|
||||
local sample=#multi.Mainloop
|
||||
local FFloadtest=0
|
||||
multi:benchMark(multi.threstimed):OnBench(function(_,l3) FFloadtest=l3*(1/multi.threstimed) end)
|
||||
self:hold(function() return FFloadtest~=0 end)
|
||||
local val=FFloadtest/sample
|
||||
multi.scheduler:Resume()
|
||||
if val>multi.threshold then
|
||||
return 0
|
||||
else
|
||||
return 100-((val/multi.threshold)*100)
|
||||
end
|
||||
end)()
|
||||
if multi.load_updater:isPaused() then multi.load_updater:Resume() return 0 end
|
||||
local val = math.abs(self.dStepA-self.dStepB)/multi.deltaTarget*100
|
||||
if val > 100 then return 100 else return val end
|
||||
end
|
||||
function multi:setDomainName(name)
|
||||
self[name]={}
|
||||
@@ -195,6 +187,7 @@ multi.Condition=multi.condition
|
||||
function multi:isHeld()
|
||||
return self.held
|
||||
end
|
||||
multi.important={}
|
||||
multi.IsHeld=multi.isHeld
|
||||
function multi.executeFunction(name,...)
|
||||
if type(_G[name])=='function' then
|
||||
@@ -214,14 +207,39 @@ end
|
||||
multi.WaitFor=multi.waitFor
|
||||
function multi:reboot(r)
|
||||
local before=collectgarbage('count')
|
||||
self.Mainloop={}
|
||||
self.Tasks={}
|
||||
self.Tasks2={}
|
||||
self.Garbage={}
|
||||
self.Children={}
|
||||
self.Paused={}
|
||||
self.Active=true
|
||||
self.Id=-1
|
||||
multi.Mainloop={}
|
||||
multi.Tasks={}
|
||||
multi.Tasks2={}
|
||||
multi.Garbage={}
|
||||
multi.ender={}
|
||||
multi.Children={}
|
||||
multi.Paused={}
|
||||
multi.Active=true
|
||||
multi.fps=60
|
||||
multi.Id=-1
|
||||
multi.Type='mainprocess'
|
||||
multi.Rest=0
|
||||
multi._type=type
|
||||
multi.Jobs={}
|
||||
multi.queue={}
|
||||
multi.jobUS=2
|
||||
multi.clock=os.clock
|
||||
multi.time=os.time
|
||||
multi.LinkedPath=multi
|
||||
multi.isRunning=false
|
||||
multi.Priority_Core=1
|
||||
multi.Priority_High=4
|
||||
multi.Priority_Above_Normal=16
|
||||
multi.Priority_Normal=64
|
||||
multi.Priority_Below_Normal=256
|
||||
multi.Priority_Low=1024
|
||||
multi.Priority_Idle=4096
|
||||
multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle}
|
||||
multi.PStep=1
|
||||
multi.PriorityTick=1
|
||||
multi.Priority=multi.Priority_Core
|
||||
multi.threshold=256
|
||||
multi.threstimed=.001
|
||||
if r then
|
||||
for i,v in pairs(_G) do
|
||||
if type(i)=='table' then
|
||||
@@ -280,20 +298,18 @@ function multi:enablePriority()
|
||||
_G.ID=0
|
||||
local PS=self
|
||||
for _D=#Loop,1,-1 do
|
||||
if Loop[_D] then
|
||||
if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then
|
||||
if Loop[_D].Active then
|
||||
Loop[_D].Id=_D
|
||||
self.CID=_D
|
||||
Loop[_D]:Act()
|
||||
for P=1,7 do
|
||||
if Loop[_D] then
|
||||
if (PS.PList[P])%Loop[_D].Priority==0 then
|
||||
if Loop[_D].Active then
|
||||
Loop[_D].Id=_D
|
||||
self.CID=_D
|
||||
Loop[_D]:Act()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
PS.PStep=PS.PStep+1
|
||||
if PS.PStep>7 then
|
||||
PS.PStep=1
|
||||
end
|
||||
end
|
||||
end
|
||||
function multi:enablePriority2()
|
||||
@@ -701,6 +717,7 @@ function multi:newProcess(file)
|
||||
loadstring('local process=multi.Cself '..io.open(file,'rb'):read('*all'))()
|
||||
end
|
||||
self:create(c)
|
||||
--~ c:IngoreObject()
|
||||
return c
|
||||
end
|
||||
function multi:newQueuer(file)
|
||||
@@ -772,7 +789,8 @@ function multi:newTimer()
|
||||
end
|
||||
function multi:newConnection(protect)
|
||||
local c={}
|
||||
setmetatable(c,{__call=function(self,...) self:connect(...) end})
|
||||
c.Parent=self
|
||||
setmetatable(c,{__call=function(self,...) return self:connect(...) end})
|
||||
c.Type='connector'
|
||||
c.func={}
|
||||
c.ID=0
|
||||
@@ -780,6 +798,16 @@ function multi:newConnection(protect)
|
||||
c.connections={}
|
||||
c.fconnections={}
|
||||
c.FC=0
|
||||
function c:holdUT()
|
||||
self.waiting=true
|
||||
local id=self:connect(function()
|
||||
self.waiting=false
|
||||
end)
|
||||
repeat
|
||||
self.Parent:uManager()
|
||||
until self.waiting==false
|
||||
id:Destroy()
|
||||
end
|
||||
function c:fConnect(func)
|
||||
local temp=self:connect(func)
|
||||
table.insert(self.fconnections,temp)
|
||||
@@ -852,8 +880,9 @@ function multi:newConnection(protect)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
temp.Destroy=temp.Remove
|
||||
if name then
|
||||
self.connections[name]=temp
|
||||
end
|
||||
@@ -1123,7 +1152,7 @@ function multi:newUpdater(skip)
|
||||
end
|
||||
self.pos=self.pos+1
|
||||
end
|
||||
function c:setSkip(n)
|
||||
function c:SetSkip(n)
|
||||
self.skip=n
|
||||
end
|
||||
c.OnUpdate=self.OnMainConnect
|
||||
@@ -1376,6 +1405,112 @@ function multi:newTStep(start,reset,count,set)
|
||||
self:create(c)
|
||||
return c
|
||||
end
|
||||
function multi:newTimeStamper()
|
||||
local c=self:newBase()
|
||||
c.Type='timestamper'
|
||||
c.Priority=self.Priority_Idle
|
||||
c.hour = {}
|
||||
c.minute = {}
|
||||
c.second = {}
|
||||
c.time = {}
|
||||
c.day = {}
|
||||
c.month = {}
|
||||
c.year = {}
|
||||
function c:Act()
|
||||
for i=1,#self.hour do
|
||||
if self.hour[i][1]==os.date("%H") and self.hour[i][3] then
|
||||
self.hour[i][2](self)
|
||||
self.hour[i][3]=false
|
||||
elseif self.hour[i][1]~=os.date("%H") and not self.hour[i][3] then
|
||||
self.hour[i][3]=true
|
||||
end
|
||||
end
|
||||
for i=1,#self.minute do
|
||||
if self.minute[i][1]==os.date("%M") and self.minute[i][3] then
|
||||
self.minute[i][2](self)
|
||||
self.minute[i][3]=false
|
||||
elseif self.minute[i][1]~=os.date("%M") and not self.minute[i][3] then
|
||||
self.minute[i][3]=true
|
||||
end
|
||||
end
|
||||
for i=1,#self.second do
|
||||
if self.second[i][1]==os.date("%S") and self.second[i][3] then
|
||||
self.second[i][2](self)
|
||||
self.second[i][3]=false
|
||||
elseif self.second[i][1]~=os.date("%S") and not self.second[i][3] then
|
||||
self.second[i][3]=true
|
||||
end
|
||||
end
|
||||
for i=1,#self.day do
|
||||
if type(self.day[i][1])=="string" then
|
||||
if self.day[i][1]==os.date("%a") and self.day[i][3] then
|
||||
self.day[i][2](self)
|
||||
self.day[i][3]=false
|
||||
elseif self.day[i][1]~=os.date("%a") and not self.day[i][3] then
|
||||
self.day[i][3]=true
|
||||
end
|
||||
else
|
||||
if string.format("%02d",self.day[i][1])==os.date("%d") and self.day[i][3] then
|
||||
self.day[i][2](self)
|
||||
self.day[i][3]=false
|
||||
elseif string.format("%02d",self.day[i][1])~=os.date("%d") and not self.day[i][3] then
|
||||
self.day[i][3]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,#self.month do
|
||||
if self.month[i][1]==os.date("%m") and self.month[i][3] then
|
||||
self.month[i][2](self)
|
||||
self.month[i][3]=false
|
||||
elseif self.month[i][1]~=os.date("%m") and not self.month[i][3] then
|
||||
self.month[i][3]=true
|
||||
end
|
||||
end
|
||||
for i=1,#self.time do
|
||||
if self.time[i][1]==os.date("%X") and self.time[i][3] then
|
||||
self.time[i][2](self)
|
||||
self.time[i][3]=false
|
||||
elseif self.time[i][1]~=os.date("%X") and not self.time[i][3] then
|
||||
self.time[i][3]=true
|
||||
end
|
||||
end
|
||||
for i=1,#self.year do
|
||||
if self.year[i][1]==os.date("%y") and self.year[i][3] then
|
||||
self.year[i][2](self)
|
||||
self.year[i][3]=false
|
||||
elseif self.year[i][1]~=os.date("%y") and not self.year[i][3] then
|
||||
self.year[i][3]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
function c:OnTime(hour,minute,second,func)
|
||||
if type(hour)=="number" then
|
||||
self.time[#self.time+1]={string.format("%02d:%02d:%02d",hour,minute,second),func,true}
|
||||
else
|
||||
self.time[#self.time+1]={hour,minute,true}
|
||||
end
|
||||
end
|
||||
function c:OnHour(hour,func)
|
||||
self.hour[#self.hour+1]={string.format("%02d",hour),func,true}
|
||||
end
|
||||
function c:OnMinute(minute,func)
|
||||
self.minute[#self.minute+1]={string.format("%02d",minute),func,true}
|
||||
end
|
||||
function c:OnSecond(second,func)
|
||||
self.second[#self.second+1]={string.format("%02d",second),func,true}
|
||||
end
|
||||
function c:OnDay(day,func)
|
||||
self.day[#self.day+1]={day,func,true}
|
||||
end
|
||||
function c:OnMonth(month,func)
|
||||
self.month[#self.month+1]={string.format("%02d",month),func,true}
|
||||
end
|
||||
function c:OnYear(year,func)
|
||||
self.year[#self.year+1]={string.format("%02d",year),func,true}
|
||||
end
|
||||
self:create(c)
|
||||
return c
|
||||
end
|
||||
function multi:newWatcher(namespace,name)
|
||||
local function WatcherObj(ns,n)
|
||||
if self.Type=='queue' then
|
||||
@@ -1462,6 +1597,7 @@ function multi:newTBase(name)
|
||||
c.important={}
|
||||
c.held=false
|
||||
c.ToString=multi.ToString
|
||||
c.ToFile=multi.ToFile
|
||||
return c
|
||||
end
|
||||
function multi:newThread(name,func)
|
||||
@@ -1992,9 +2128,15 @@ function multi:newThreadedEvent(name,task)
|
||||
return c
|
||||
end
|
||||
-- State Saving Stuff
|
||||
function multi:IngoreObject()
|
||||
self.Ingore=true
|
||||
end
|
||||
multi.scheduler:IngoreObject()
|
||||
function multi:ToString()
|
||||
if self.Ingore then return end
|
||||
local t=self.Type
|
||||
local data;
|
||||
print(t)
|
||||
if t:sub(-6)=="Thread" then
|
||||
data={
|
||||
Type=t,
|
||||
@@ -2025,9 +2167,7 @@ function multi:ToString()
|
||||
held=self.held,
|
||||
}
|
||||
end
|
||||
if t=="process" then
|
||||
--
|
||||
elseif t=="eventThread" or t=="event" then
|
||||
if t=="eventThread" or t=="event" then
|
||||
table.merge(data,{
|
||||
Task=self.Task,
|
||||
})
|
||||
@@ -2095,6 +2235,23 @@ function multi:ToString()
|
||||
set=self.set,
|
||||
link=self.link,
|
||||
})
|
||||
elseif t=="process" or t=="mainprocess" then
|
||||
local loop=self.Mainloop
|
||||
local dat={}
|
||||
for i=1,#loop do
|
||||
local ins=loop[i]:ToString()
|
||||
if ins~=nil then
|
||||
table.insert(dat,ins)
|
||||
end
|
||||
end
|
||||
local str=bin.new()
|
||||
str:addBlock({Type=t})
|
||||
str:addBlock(#dat,4,"n")
|
||||
for i=1,#dat do
|
||||
str:addBlock(#dat[i],4,"n")
|
||||
str:addBlock(dat[i])
|
||||
end
|
||||
return str.data
|
||||
end
|
||||
for i,v in pairs(self.important) do
|
||||
data[v]=self[v]
|
||||
@@ -2109,9 +2266,23 @@ function multi:newFromString(str)
|
||||
str=str.data
|
||||
end
|
||||
end
|
||||
local data=bin.new(str):getBlock("t")
|
||||
local handle=bin.new(str)
|
||||
local data=handle:getBlock("t")
|
||||
local t=data.Type
|
||||
if t=="step" then -- GOOD
|
||||
if t=="mainprocess" then
|
||||
local objs=handle:getBlock("n",4)
|
||||
for i=1,objs do
|
||||
self:newFromString(handle:getBlock("s",(handle:getBlock("n",4))))
|
||||
end
|
||||
return self
|
||||
elseif t=="process" then
|
||||
local temp=multi:newProcess()
|
||||
local objs=handle:getBlock("n",4)
|
||||
for i=1,objs do
|
||||
temp:newFromString(handle:getBlock("s",(handle:getBlock("n",4))))
|
||||
end
|
||||
return temp
|
||||
elseif t=="step" then -- GOOD
|
||||
local item=self:newStep()
|
||||
table.merge(item,data)
|
||||
return item
|
||||
@@ -2176,6 +2347,12 @@ end
|
||||
function multi:Important(varname)
|
||||
table.insert(important,varname)
|
||||
end
|
||||
function multi:ToFile(path)
|
||||
bin.new(self:ToString()):tofile(path)
|
||||
end
|
||||
function multi:fromFile(path)
|
||||
self:newFromString(bin.load(path))
|
||||
end
|
||||
function multi:SetStateFlag(opt)
|
||||
--
|
||||
end
|
||||
@@ -2191,3 +2368,18 @@ end
|
||||
function multi:setDefualtStateFlag(opt)
|
||||
--
|
||||
end
|
||||
multi.dStepA = 0
|
||||
multi.dStepB = 0
|
||||
multi.dSwap = 0
|
||||
multi.deltaTarget = .05
|
||||
multi.load_updater = multi:newUpdater(2)
|
||||
multi.load_updater:Pause()
|
||||
multi.load_updater:OnUpdate(function(self)
|
||||
if self.Parent.dSwap == 0 then
|
||||
self.Parent.dStepA = os.clock()
|
||||
self.Parent.dSwap = 1
|
||||
else
|
||||
self.Parent.dSwap = 0
|
||||
self.Parent.dStepB = os.clock()
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -89,7 +89,10 @@ else
|
||||
THREAD.__CORES=tonumber(io.popen("nproc --all"):read("*n"))
|
||||
end
|
||||
function THREAD.kill() -- trigger the lane destruction
|
||||
-- coroutine.yield({"_kill_",":)"})
|
||||
error("Thread was killed!")
|
||||
end
|
||||
function THREAD.getName()
|
||||
return THREAD_NAME
|
||||
end
|
||||
--[[ Step 4 We need to get sleeping working to handle timing... We want idle wait, not busy wait
|
||||
Idle wait keeps the CPU running better where busy wait wastes CPU cycles... Lanes does not have a sleep method
|
||||
@@ -111,7 +114,12 @@ function multi:newSystemThread(name,func,...)
|
||||
local __self=c
|
||||
c.name=name
|
||||
c.Type="sthread"
|
||||
c.thread=lanes.gen("*", func)(...)
|
||||
local THREAD_NAME=name
|
||||
local function func2(...)
|
||||
_G["THREAD_NAME"]=THREAD_NAME
|
||||
func()
|
||||
end
|
||||
c.thread=lanes.gen("*", func2)(...)
|
||||
function c:kill()
|
||||
--self.status:Destroy()
|
||||
self.thread:cancel()
|
||||
|
||||
@@ -9,11 +9,12 @@ multi.integration={}
|
||||
multi.integration.love2d={}
|
||||
multi.integration.love2d.ThreadBase=[[
|
||||
tab={...}
|
||||
__THREADID__=table.remove(1,tab)
|
||||
__THREADNAME__=table.remove(1,tab)
|
||||
__THREADID__=table.remove(tab,1)
|
||||
__THREADNAME__=table.remove(tab,1)
|
||||
require("love.filesystem")
|
||||
require("love.system")
|
||||
require("love.timer")
|
||||
require("love.image")
|
||||
require("multi")
|
||||
GLOBAL={}
|
||||
setmetatable(GLOBAL,{
|
||||
@@ -34,7 +35,7 @@ setmetatable(GLOBAL,{
|
||||
function __sync__()
|
||||
local data=__mythread__:pop()
|
||||
while data do
|
||||
love.timer.sleep(.001)
|
||||
love.timer.sleep(.01)
|
||||
if type(data)=="string" then
|
||||
local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)")
|
||||
if name=="__DIEPLZ"..__THREADID__.."__" then
|
||||
@@ -139,6 +140,12 @@ function dump(func)
|
||||
end
|
||||
return table.concat(code)
|
||||
end
|
||||
function sThread.getName()
|
||||
return __THREADNAME__
|
||||
end
|
||||
function sThread.kill()
|
||||
error("Thread was killed!")
|
||||
end
|
||||
function sThread.set(name,val)
|
||||
GLOBAL[name]=val
|
||||
end
|
||||
@@ -158,14 +165,6 @@ end
|
||||
function sThread.hold(n)
|
||||
repeat __sync__() until n()
|
||||
end
|
||||
multi:newLoop(function(self)
|
||||
self:Pause()
|
||||
local ld=multi:getLoad()
|
||||
self:Resume()
|
||||
if ld<80 then
|
||||
love.timer.sleep(.01)
|
||||
end
|
||||
end)
|
||||
updater=multi:newUpdater()
|
||||
updater:OnUpdate(__sync__)
|
||||
func=loadDump([=[INSERT_USER_CODE]=])(unpack(tab))
|
||||
@@ -190,6 +189,9 @@ setmetatable(GLOBAL,{
|
||||
})
|
||||
THREAD={} -- Allow main thread to interact with these objects as well
|
||||
multi.integration.love2d.mainChannel=love.thread.getChannel("__MainChan__")
|
||||
function THREAD.getName()
|
||||
return __THREADNAME__
|
||||
end
|
||||
function ToStr(val, name, skipnewlines, depth)
|
||||
skipnewlines = skipnewlines or false
|
||||
depth = depth or 0
|
||||
|
||||
@@ -37,19 +37,62 @@ function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a chann
|
||||
function c:init() -- create an init function so we can mimic on bith love2d and lanes
|
||||
self.chan=love.thread.getChannel(self.name) -- create channel by the name self.name
|
||||
function self:push(v) -- push to the channel
|
||||
self.chan:push({type(v),resolveData(v)})
|
||||
local tab
|
||||
if type(v)=="table" then
|
||||
tab = {}
|
||||
for i,c in pairs(v) do
|
||||
if type(c)=="function" then
|
||||
tab[i]="\1"..string.dump(c)
|
||||
else
|
||||
tab[i]=c
|
||||
end
|
||||
end
|
||||
self.chan:push(tab)
|
||||
else
|
||||
self.chan:push(c)
|
||||
end
|
||||
end
|
||||
function self:pop() -- pop from the channel
|
||||
local tab=self.chan:pop()
|
||||
--print(tab)
|
||||
if not tab then return end
|
||||
return resolveType(tab[1],tab[2])
|
||||
local v=self.chan:pop()
|
||||
if not v then return end
|
||||
if type(v)=="table" then
|
||||
tab = {}
|
||||
for i,c in pairs(v) do
|
||||
if type(c)=="string" then
|
||||
if c:sub(1,1)=="\1" then
|
||||
tab[i]=loadstring(c:sub(2,-1))
|
||||
else
|
||||
tab[i]=c
|
||||
end
|
||||
else
|
||||
tab[i]=c
|
||||
end
|
||||
end
|
||||
return tab
|
||||
else
|
||||
return self.chan:pop()
|
||||
end
|
||||
end
|
||||
function self:peek()
|
||||
local tab=self.chan:peek()
|
||||
--print(tab)
|
||||
if not tab then return end
|
||||
return resolveType(tab[1],tab[2])
|
||||
local v=self.chan:peek()
|
||||
if not v then return end
|
||||
if type(v)=="table" then
|
||||
tab = {}
|
||||
for i,c in pairs(v) do
|
||||
if type(c)=="string" then
|
||||
if c:sub(1,1)=="\1" then
|
||||
tab[i]=loadstring(c:sub(2,-1))
|
||||
else
|
||||
tab[i]=c
|
||||
end
|
||||
else
|
||||
tab[i]=c
|
||||
end
|
||||
end
|
||||
return tab
|
||||
else
|
||||
return self.chan:pop()
|
||||
end
|
||||
end
|
||||
GLOBAL[self.name]=self -- send the object to the thread through the global interface
|
||||
return self -- return the object
|
||||
@@ -120,7 +163,7 @@ function multi:systemThreadedBenchmark(n,p)
|
||||
end)
|
||||
return c
|
||||
end
|
||||
function multi:newSystemThreadedTable(name,n)
|
||||
function multi:newSystemThreadedTable(name,n) -- NEDS FIXING SING SO MUCH WORK!!!
|
||||
local c={} -- where we will store our object
|
||||
c.name=name -- set the name this is important for the love2d side
|
||||
c.cores=n
|
||||
@@ -212,8 +255,7 @@ function multi:newSystemThreadedJobQueue(numOfCores)
|
||||
c.queueOUT=multi:newSystemThreadedQueue("THREADED_JQO"):init()
|
||||
c.queueALL=multi:newSystemThreadedQueue("THREADED_QALL"):init()
|
||||
c.REG=multi:newSystemThreadedQueue("THREADED_JQ_F_REG"):init()
|
||||
-- registerJob(name,func)
|
||||
-- pushJob(...)
|
||||
c.OnReady=multi:newConnection()
|
||||
function c:registerJob(name,func)
|
||||
for i=1,self.cores do
|
||||
self.REG:push({name,func})
|
||||
@@ -222,6 +264,7 @@ function multi:newSystemThreadedJobQueue(numOfCores)
|
||||
function c:pushJob(name,...)
|
||||
self.queueOUT:push({self.jobnum,name,...})
|
||||
self.jobnum=self.jobnum+1
|
||||
return self.jobnum-1
|
||||
end
|
||||
local GLOBAL=multi.integration.GLOBAL -- set up locals incase we are using lanes
|
||||
local sThread=multi.integration.THREAD -- set up locals incase we are using lanes
|
||||
@@ -232,15 +275,24 @@ function multi:newSystemThreadedJobQueue(numOfCores)
|
||||
end
|
||||
end
|
||||
function c:start()
|
||||
self:doToAll(function()
|
||||
_G["__started__"]=true
|
||||
SFunc()
|
||||
multi:newEvent(function()
|
||||
return self.ThreadsLoaded==true
|
||||
end):OnEvent(function(evnt)
|
||||
GLOBAL["THREADED_JQ"]=nil -- remove it
|
||||
GLOBAL["THREADED_JQO"]=nil -- remove it
|
||||
GLOBAL["THREADED_JQ_F_REG"]=nil -- remove it
|
||||
self:doToAll(function()
|
||||
_G["__started__"]=true
|
||||
SFunc()
|
||||
end)
|
||||
evnt:Destroy()
|
||||
end)
|
||||
end
|
||||
GLOBAL["__JQ_COUNT__"]=c.cores
|
||||
for i=1,c.cores do
|
||||
multi:newSystemThread("System Threaded Job Queue Worker Thread #"..i,function()
|
||||
multi:newSystemThread("System Threaded Job Queue Worker Thread #"..i,function(name,ind)
|
||||
require("multi")
|
||||
ThreadName=name
|
||||
__sleep__=.001
|
||||
if love then -- lets make sure we don't reference upvalues if using love2d
|
||||
GLOBAL=_G.GLOBAL
|
||||
@@ -251,10 +303,6 @@ function multi:newSystemThreadedJobQueue(numOfCores)
|
||||
JQO=sThread.waitFor("THREADED_JQ"):init() -- Grab it
|
||||
REG=sThread.waitFor("THREADED_JQ_F_REG"):init() -- Grab it
|
||||
QALL=sThread.waitFor("THREADED_QALL"):init() -- Grab it
|
||||
sThread.sleep(.1) -- lets wait for things to work out
|
||||
GLOBAL["THREADED_JQ"]=nil -- remove it
|
||||
GLOBAL["THREADED_JQO"]=nil -- remove it
|
||||
GLOBAL["THREADED_JQ_F_REG"]=nil -- remove it
|
||||
QALLT={}
|
||||
FUNCS={}
|
||||
SFunc=multi:newFunction(function(self)
|
||||
@@ -287,10 +335,12 @@ function multi:newSystemThreadedJobQueue(numOfCores)
|
||||
return FUNCS[k]
|
||||
end
|
||||
})
|
||||
lastjob=os.clock()
|
||||
MainLoop=multi:newLoop(function(self)
|
||||
if __started__ then
|
||||
local job=JQI:pop()
|
||||
if job then
|
||||
lastjob=os.clock()
|
||||
local d=QALL:peek()
|
||||
if d then
|
||||
if not QALLT[d[1]] then
|
||||
@@ -311,17 +361,34 @@ function multi:newSystemThreadedJobQueue(numOfCores)
|
||||
end
|
||||
end
|
||||
end)
|
||||
multi:newThread("Idler",function()
|
||||
while true do
|
||||
if os.clock()-lastjob>1 then
|
||||
sThread.sleep(.1)
|
||||
end
|
||||
thread.sleep(.001)
|
||||
end
|
||||
end)
|
||||
JQO:push({"_THREADINIT_",ind})
|
||||
if not love then
|
||||
multi:mainloop()
|
||||
end
|
||||
end)
|
||||
end,"Thread<"..i..">",i)
|
||||
end
|
||||
c.OnJobCompleted=multi:newConnection()
|
||||
c.updater=multi:newLoop(function(self)
|
||||
local data=self.link.queueIN:pop()
|
||||
while data do
|
||||
if data then
|
||||
self.link.OnJobCompleted:Fire(unpack(data))
|
||||
local a,b=unpack(data)
|
||||
if a=="_THREADINIT_" then
|
||||
if b==self.link.cores then
|
||||
self.link.ThreadsLoaded=true
|
||||
self.link.OnReady:Fire()
|
||||
end
|
||||
else
|
||||
self.link.OnJobCompleted:Fire(unpack(data))
|
||||
end
|
||||
end
|
||||
data=self.link.queueIN:pop()
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user