(1.8.4) Update

This commit is contained in:
2017-07-03 13:59:44 -04:00
parent 367982898a
commit 584e8be3a2
21 changed files with 1027 additions and 151 deletions
+34
View File
@@ -0,0 +1,34 @@
package.path="?/init.lua;?.lua;"..package.path
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
multi:newAlarm(2):OnRing(function(self)
GLOBAL["NumOfCores"]=sThread.getCores()
end)
multi:newAlarm(7):OnRing(function(self)
GLOBAL["AnotherTest"]=true
end)
multi:newAlarm(13):OnRing(function(self)
GLOBAL["FinalTest"]=true
end)
multi:newSystemThread("test",function() -- spawns a thread in another lua process
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
print("Waiting for variable: NumOfCores")
print("Got it: ",sThread.waitFor("NumOfCores"))
sThread.hold(function()
return GLOBAL["AnotherTest"] -- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded...
end)
print("Holding works!")
multi:newThread("tests",function()
thread.hold(function()
return GLOBAL["FinalTest"] -- note this will not hold the entire systemthread. As seen with the TLoop constantly going!
end)
print("Final test works!")
os.exit()
end)
local a=0
multi:newTLoop(function()
a=a+1
print(a)
end,.5)
multi:mainloop()
end)
multi:mainloop()
+59
View File
@@ -0,0 +1,59 @@
package.path="?/init.lua;?.lua;"..package.path
local GLOBAL,sThread=require("multi.integration.lanesManager").init() -- loads the lanesManager and includes the entire multi library
local function comma_value(amount)
local formatted = amount
while true do
formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
if (k==0) then
break
end
end
return formatted
end
multi:newSystemThread("test1",function() -- spawns a thread in another lua process
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 1"):OnBench(function(self,c) GLOBAL["T1"]=c multi:Stop() end)
multi:mainloop()
end)
multi:newSystemThread("test2",function() -- spawns a thread in another lua process
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 2"):OnBench(function(self,c) GLOBAL["T2"]=c multi:Stop() end)
multi:mainloop()
end)
multi:newSystemThread("test3",function() -- spawns a thread in another lua process
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 3"):OnBench(function(self,c) GLOBAL["T3"]=c multi:Stop() end)
multi:mainloop()
end)
multi:newSystemThread("test4",function() -- spawns a thread in another lua process
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 4"):OnBench(function(self,c) GLOBAL["T4"]=c multi:Stop() end)
multi:mainloop()
end)
multi:newSystemThread("test5",function() -- spawns a thread in another lua process
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 5"):OnBench(function(self,c) GLOBAL["T5"]=c multi:Stop() end)
multi:mainloop()
end)
multi:newSystemThread("test6",function() -- spawns a thread in another lua process
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 6"):OnBench(function(self,c) GLOBAL["T6"]=c multi:Stop() end)
multi:mainloop()
print("Bench: ",comma_value(tostring(sThread.waitFor("T1")+sThread.waitFor("T2")+sThread.waitFor("T3")+sThread.waitFor("T4")+sThread.waitFor("T5")+sThread.waitFor("T6"))))
GLOBAL["DONE"]=true
end)
multi:newThread("test0",function()
-- sThread.waitFor("DONE") -- lets hold the main thread completely so we don't eat up cpu
-- os.exit()
-- when the main thread is holding there is a chance that error handling on the system threads may not work!
-- instead we can do this
while true do
thread.skip(1) -- allow error handling to take place... Otherwise lets keep the main thread running on the low
sThread.sleep(.001) -- Sleeping for .001 is a greeat way to keep cpu usage down. Make sure if you aren't doing work to rest. Abuse the hell out of GLOBAL if you need to :P
if GLOBAL["DONE"] then
os.exit()
end
end
end)
GLOBAL["Bench"]=60
multi:mainloop()
+48
View File
@@ -0,0 +1,48 @@
package.path="?/init.lua;?.lua;"..package.path -- Spawing threads using 1 method and the sThread.getCores() function!
local GLOBAL,sThread=require("multi.integration.lanesManager").init() -- loads the lanesManager and includes the entire multi library
local function comma_value(amount)
local formatted = amount
while true do
formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
if (k==0) then
break
end
end
return formatted
end
GLOBAL["BENCHCOUNT"],GLOBAL["CNUM"],GLOBAL["DONE"]=0,0,0
cores=sThread.getCores()
function benchmark() -- our single function that will be used across a bunch of threads
require("multi.all") -- get the library
local n=GLOBAL["CNUM"]; GLOBAL["CNUM"]=n+1 -- do some math so we can identify which thread is which
multi:benchMark(sThread.waitFor("BENCH"),nil,"Thread "..n+1):OnBench(function(self,c) GLOBAL["BENCHCOUNT"]=GLOBAL["BENCHCOUNT"]+c; GLOBAL["DONE"]=GLOBAL["DONE"]+1; multi:Stop() end)
-- ^ do the bench mark and add to the BENCHCOUNT GLOBAL value, then increment the DONE Value
multi:mainloop()
end
for i=1,cores do -- loop based on the number of cores you have
multi:newSystemThread("test"..i,benchmark) -- create a system thread based on the benchmark
end
multi:newThread("test0",function()
while true do
thread.skip(1)
sThread.sleep(.001)
if GLOBAL["DONE"]==cores then
print(comma_value(tostring(GLOBAL["BENCHCOUNT"])))
os.exit()
end
end
end)
GLOBAL["BENCH"]=10
print("Platform is: ",multi:getPlatform()) -- returns love2d or lanes depending on which platform you are using... If I add more intergrations then this method will be updated! corona sdk may see this library in the future...
multi:mainloop()
--[[ Output on my machine! I am using luajit and have 6 cores on my computer. Your numbers will vary, but it should look something like this
Intergrated Lanes!
Platform is: lanes
Thread 1 62442125 Steps in 10 second(s)!
Thread 2 61379095 Steps in 10 second(s)!
Thread 3 62772502 Steps in 10 second(s)!
Thread 4 62740684 Steps in 10 second(s)!
Thread 5 60926715 Steps in 10 second(s)!
Thread 6 61793175 Steps in 10 second(s)!
372,054,296
]]
+27
View File
@@ -0,0 +1,27 @@
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
queue=multi:newSystemThreadedQueue("QUEUE"):init()
queue:push("This is a test")
queue:push("This is a test2")
queue:push("This is a test3")
queue:push("This is a test4")
multi:newSystemThread("test2",function()
queue=sThread.waitFor("QUEUE"):init()
data=queue:pop()
while data do
print(data)
data=queue:pop()
end
queue:push("This is a test5")
queue:push("This is a test6")
queue:push("This is a test7")
queue:push("This is a test8")
end)
multi:newThread("test!",function() -- this is a lua thread
thread.sleep(.1)
data=queue:pop()
while data do
print(data)
data=queue:pop()
end
end)
multi:mainloop()
+28
View File
@@ -0,0 +1,28 @@
package.path="?/init.lua;"..package.path -- slightly different usage of the code
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
queue=multi:newSystemThreadedQueue("QUEUE")
queue:push(1)
queue:push(2)
queue:push(3)
queue:push(4)
queue:push(5)
queue:push(6)
multi:newSystemThread("STHREAD_1",function()
queue=sThread.waitFor("QUEUE"):init()
GLOBAL["QUEUE"]=nil
data=queue:pop()
while data do
print(data)
data=queue:pop()
end
end)
multi:newThread("THREAD_1",function()
while true do
if GLOBAL["QUEUE"]==nil then
print("Deleted a Global!")
break
end
thread.skip(1)
end
end)
multi:mainloop()
+14
View File
@@ -0,0 +1,14 @@
-- lanes Desktop lua! NOTE: this is in lanesintergratetest6.lua in the examples folder
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
test=multi:newSystemThreadedTable("YO"):init()
test["test1"]="lol"
multi:newSystemThread("test",function()
tab=sThread.waitFor("YO"):init()
print(tab["test1"])
sThread.sleep(3)
tab["test2"]="Whats so funny?"
end)
multi:newThread("test2",function()
print(test:waitFor("test2"))
end)
multi:mainloop()
+28
View File
@@ -0,0 +1,28 @@
-- Creating the object using lanes manager to show case this. Examples has the file for love2d
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
jQueue=multi:newSystemThreadedJobQueue(n) -- this internally creates System threads. By defualt it will use the # of processors on your system You can set this number though.
-- Only create 1 jobqueue! For now making more than 1 is buggy. You only really need one though. Just register new functions if you want 1 queue to do more. The one reason though is keeping track of jobIDs. I have an idea that I will roll out in the next update.
jQueue:registerJob("TEST_JOB",function(a,s)
math.randomseed(s)
-- We will push a random #
TEST_JOB2() -- You can call other registered functions as well!
return math.random(0,255) -- send the result to the main thread
end)
jQueue:registerJob("TEST_JOB2",function()
print("Test Works!") -- this is called from the job since it is registered on the same queue
end)
tableOfOrder={} -- This is how we will keep order of our completed jobs. There is no guarantee that the order will be correct
jQueue.OnJobCompleted(function(JOBID,n) -- whenever a job is completed you hook to the event that is called. This passes the JOBID folled by the returns of the job
-- JOBID is the completed job, starts at 1 and counts up by 1.
-- Threads finish at different times so jobids may be passed out of order! Be sure to have a way to order them
tableOfOrder[JOBID]=n -- we order ours by putting them into a table
if #tableOfOrder==10 then
print("We got all of the pieces!")
end
end)
-- LEts push the jobs now
for i=1,10 do -- Job Name of registered function, ... varargs
jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000))
end
print("I pushed all of the jobs :)")
multi:mainloop() -- Start the main loop :D
@@ -0,0 +1,31 @@
require("core.Library")
GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library
require("core.GuiManager")
gui.ff.Color=Color.Black
jQueue=multi:newSystemThreadedJobQueue() -- this internally creates System threads, We told it to use a maximum of 3 cores at any given time
jQueue:registerJob("TEST_JOB",function(a,s)
math.randomseed(s)
print("testing...")
-- We will push a random #
TEST_JOB2() -- You can call other registered functions as well!
return math.random(0,255) -- send the result to the main thread
end)
jQueue:registerJob("TEST_JOB2",function(a,s)
print("Test Works!")
end)
tableOfOrder={}
jQueue.OnJobCompleted(function(JOBID,n)
-- JOBID is the completed job, starts at 1 and counts up by 1.
-- Threads finish at different times so jobids may be returned out of order! Be sure to have a way to order them
tableOfOrder[JOBID]=n -- we order ours by putting them into a table
if #tableOfOrder==10 then
print("We got all of the pieces!")
end
end)
for i=1,10 do -- Job Name of registered function, ... varargs
jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000))
end
print("I pushed all of the jobs :)")
t=gui:newTextLabel("no done yet!",0,0,300,100)
t:centerX()
t:centerY()
@@ -45,8 +45,8 @@ function print(...)
end
end
multi = {}
multi.Version="1.8.2"
multi._VERSION="1.8.2"
multi.Version="1.8.4"
multi._VERSION="1.8.4"
multi.stage='stable'
multi.__index = multi
multi.Mainloop={}
@@ -108,11 +108,13 @@ function multi:setThrestimed(n)
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
@@ -617,7 +619,11 @@ function multi:hold(task)
env:OnEvent(function(envt) envt:Pause() envt.Active=false end)
while env.Active do
if love then
self.Parent:lManager()
if love.graphics then
self.Parent:lManager()
else
self.Parent:Do_Order()
end
else
self.Parent:Do_Order()
end
@@ -978,7 +984,110 @@ function multi:mainloop()
else
return "Already Running!"
end
--print("Did you call multi:Stop()? This method should not be used when using multi:mainloop() unless of course you wanted to stop it! you can restart the multi, by using multi:reboot() and calling multi:mainloop() again or by using multi:uManager()")
end
function multi:protectedMainloop()
multi:protect()
if not multi.isRunning then
multi.isRunning=true
for i=1,#self.Tasks do
self.Tasks[i](self)
end
rawset(self,'Start',self.clock())
while self.Active do
self:Do_Order()
end
else
return "Already Running!"
end
end
function multi:unprotectedMainloop()
multi:unProtect()
if not multi.isRunning then
multi.isRunning=true
for i=1,#self.Tasks do
self.Tasks[i](self)
end
rawset(self,'Start',self.clock())
while self.Active do
local Loop=self.Mainloop
_G.ID=0
for _D=#Loop,1,-1 do
if Loop[_D] then
if Loop[_D].Active then
Loop[_D].Id=_D
self.CID=_D
Loop[_D]:Act()
end
end
end
end
else
return "Already Running!"
end
end
function multi:prioritizedMainloop1()
multi:enablePriority()
if not multi.isRunning then
multi.isRunning=true
for i=1,#self.Tasks do
self.Tasks[i](self)
end
rawset(self,'Start',self.clock())
while self.Active do
local Loop=self.Mainloop
_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()
end
end
end
end
PS.PStep=PS.PStep+1
if PS.PStep>7 then
PS.PStep=1
end
end
else
return "Already Running!"
end
end
function multi:prioritizedMainloop2()
multi:enablePriority2()
if not multi.isRunning then
multi.isRunning=true
for i=1,#self.Tasks do
self.Tasks[i](self)
end
rawset(self,'Start',self.clock())
while self.Active do
local Loop=self.Mainloop
_G.ID=0
local PS=self
for _D=#Loop,1,-1 do
if Loop[_D] then
if (PS.PStep)%Loop[_D].Priority==0 then
if Loop[_D].Active then
Loop[_D].Id=_D
self.CID=_D
Loop[_D]:Act()
end
end
end
end
PS.PStep=PS.PStep+1
if PS.PStep>self.Priority_Idle then
PS.PStep=1
end
end
else
return "Already Running!"
end
end
function multi._tFunc(self,dt)
for i=1,#self.Tasks do
@@ -1494,7 +1603,7 @@ function multi:newThread(name,func)
end
multi:setDomainName("Threads")
multi:setDomainName("Globals")
multi.scheduler=multi:newUpdater()
multi.scheduler=multi:newLoop()
multi.scheduler.Type="scheduler"
function multi.scheduler:setStep(n)
self.skip=tonumber(n) or 24
@@ -1503,7 +1612,7 @@ multi.scheduler.skip=0
multi.scheduler.counter=0
multi.scheduler.Threads=multi:linkDomain("Threads")
multi.scheduler.Globals=multi:linkDomain("Globals")
multi.scheduler:OnUpdate(function(self)
multi.scheduler:OnLoop(function(self)
self.counter=self.counter+1
for i=#self.Threads,1,-1 do
ret={}
@@ -1557,7 +1666,6 @@ multi.scheduler:OnUpdate(function(self)
end
end
end)
multi.scheduler:setStep()
multi.scheduler:Pause()
multi.OnError=multi:newConnection()
function multi:newThreadedAlarm(name,set)
@@ -125,12 +125,9 @@ function multi:newSystemThread(name,func)
end)
return c
end
print("Intergrated Lanes!")
multi.intergration={} -- for module creators
multi.intergration.GLOBAL=GLOBAL
multi.intergration.THREAD=THREAD
multi.intergration.lanes={}
multi.intergration.lanes.GLOBAL=GLOBAL -- for module creators
multi.intergration.lanes.THREAD=THREAD -- for module creators
require("multi.intergration.shared.shared")
print("Integrated Lanes!")
multi.integration={} -- for module creators
multi.integration.GLOBAL=GLOBAL
multi.integration.THREAD=THREAD
require("multi.integration.shared.shared")
return {init=function() return GLOBAL,THREAD end}
@@ -2,14 +2,14 @@ require("multi.compat.love2d")
function multi:canSystemThread()
return true
end
multi.intergration={}
multi.intergration.love2d={}
multi.intergration.love2d.ThreadBase=[[
multi.integration={}
multi.integration.love2d={}
multi.integration.love2d.ThreadBase=[[
__THREADNAME__=({...})[1]
require("love.filesystem")
require("love.system")
require("love.timer")
require("multi.all")
require("multi")
GLOBAL={}
setmetatable(GLOBAL,{
__index=function(t,k)
@@ -29,6 +29,7 @@ setmetatable(GLOBAL,{
function __sync__()
local data=__mythread__:pop()
while data do
love.timer.sleep(.001)
if type(data)=="string" then
local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)")
if name=="__DIEPLZ"..__THREADNAME__.."__" then
@@ -79,7 +80,7 @@ function resolveType(tp,d)
elseif tp=="bool" then
return (d=="true")
elseif tp=="function" then
return loadDump(d)
return loadDump("[==["..d.."]==]")
elseif tp=="table" then
return loadstring("return "..d)()
elseif tp=="nil" then
@@ -91,11 +92,11 @@ end
function resolveData(v)
local data=""
if type(v)=="table" then
data=ToStr(v)
return ToStr(v)
elseif type(v)=="function" then
data=dump(v)
return dump(v)
elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then
data=tostring(v)
return tostring(v)
end
return data
end
@@ -152,24 +153,16 @@ end
function sThread.hold(n)
repeat __sync__() until n()
end
updater=multi:newUpdater()
updater:OnUpdate(function(self)
local data=__mythread__:pop()
while data do
if type(data)=="string" then
local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)")
if name=="__DIEPLZ"..__THREADNAME__.."__" then
error("Thread: "..__THREADNAME__.." has been stopped!")
end
if cmd=="SYNC" then
__proxy__[name]=resolveType(tp,d)
end
else
__proxy__[name]=data
end
data=__mythread__:pop()
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]=])()
multi:mainloop()
]]
@@ -191,7 +184,7 @@ setmetatable(GLOBAL,{
end,
})
THREAD={} -- Allow main thread to interact with these objects as well
multi.intergration.love2d.mainChannel=love.thread.getChannel("__MainChan__")
multi.integration.love2d.mainChannel=love.thread.getChannel("__MainChan__")
function ToStr(val, name, skipnewlines, depth)
skipnewlines = skipnewlines or false
depth = depth or 0
@@ -228,7 +221,7 @@ function resolveType(tp,d)
elseif tp=="bool" then
return (d=="true")
elseif tp=="function" then
return loadDump(d)
return loadDump("[==["..d.."]==]")
elseif tp=="table" then
return loadstring("return "..d)()
elseif tp=="nil" then
@@ -240,11 +233,11 @@ end
function resolveData(v)
local data=""
if type(v)=="table" then
data=ToStr(v)
return ToStr(v)
elseif type(v)=="function" then
data=dump(v)
return dump(v)
elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then
data=tostring(v)
return tostring(v)
end
return data
end
@@ -274,10 +267,10 @@ function multi:newSystemThread(name,func) -- the main method
local c={}
c.name=name
c.ID=c.name.."<ID|"..randomString(8)..">"
c.thread=love.thread.newThread(multi.intergration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func)))
c.thread=love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func)))
c.thread:start(c.ID)
function c:kill()
multi.intergration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__"
multi.integration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__"
end
return c
end
@@ -310,11 +303,11 @@ function THREAD.hold(n)
multi.OBJ_REF:Resume()
end
__channels__={}
multi.intergration.GLOBAL=GLOBAL
multi.intergration.THREAD=THREAD
multi.integration.GLOBAL=GLOBAL
multi.integration.THREAD=THREAD
updater=multi:newUpdater()
updater:OnUpdate(function(self)
local data=multi.intergration.love2d.mainChannel:pop()
local data=multi.integration.love2d.mainChannel:pop()
while data do
--print("MAIN:",data)
if type(data)=="string" then
@@ -342,19 +335,21 @@ updater:OnUpdate(function(self)
else
__proxy__[name]=data
end
data=multi.intergration.love2d.mainChannel:pop()
data=multi.integration.love2d.mainChannel:pop()
end
end)
require("multi.intergration.shared.shared")
print("Intergrated Love2d!")
require("multi.integration.shared.shared")
print("Integrated Love2d!")
return {
init=function(t)
if t then
if t.threadNamespace then
multi.intergration.love2d.ThreadBase:gsub("sThread",t.threadNamespace)
multi.integration.THREADNAME=t.threadNamespace
multi.integration.love2d.ThreadBase:gsub("sThread",t.threadNamespace)
end
if t.globalNamespace then
multi.intergration.love2d.ThreadBase:gsub("GLOBAL",t.globalNamespace)
multi.integration.GLOBALNAME=t.globalNamespace
multi.integration.love2d.ThreadBase:gsub("GLOBAL",t.globalNamespace)
end
end
return GLOBAL,THREAD
@@ -29,10 +29,16 @@ 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(v)
self.chan:push({type(v),resolveData(v)})
end
function self:pop() -- pop from the channel
return self.chan:pop()
local tab=self.chan:pop()
if not tab then return end
return resolveType(tab[1],tab[2])
end
function self:peek()
local tp,d=unpack{self.chan:peek()}
return resolveType(tp,d)
end
GLOBAL[self.name]=self -- send the object to the thread through the global interface
return self -- return the object
@@ -49,20 +55,23 @@ function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a chann
function c:pop() -- pop the queue
return ({self.linda:receive(0,"Q")})[2]
end
function c:peek()
return self.linda:get("Q")
end
function c:init() -- mimic the feature that love2d requires, so code can be consistent
return self
end
multi.intergration.GLOBAL[name]=c -- send the object to the thread through the global interface
multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface
end
return c
end
function multi:systemThreadedBenchmark(n,p)
n=n or 1
local cores=multi.intergration.THREAD.getCores()
local cores=multi.integration.THREAD.getCores()
local queue=multi:newSystemThreadedQueue("QUEUE")
multi.intergration.GLOBAL["__SYSTEMBENCHMARK__"]=n
local sThread=multi.intergration.THREAD
local GLOBAL=multi.intergration.GLOBAL
multi.integration.GLOBAL["__SYSTEMBENCHMARK__"]=n
local sThread=multi.integration.THREAD
local GLOBAL=multi.integration.GLOBAL
for i=1,cores do
multi:newSystemThread("STHREAD_BENCH",function()
require("multi")
@@ -170,7 +179,129 @@ function multi:newSystemThreadedTable(name)
})
return self
end
multi.intergration.GLOBAL[name]=c -- send the object to the thread through the global interface
multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface
end
return c
end
function multi:newSystemThreadedJobQueue(numOfCores)
local c={}
c.jobnum=1
c.cores=numOfCores or multi.integration.THREAD.getCores()
c.queueIN=multi:newSystemThreadedQueue("THREADED_JQ"):init()
c.queueOUT=multi:newSystemThreadedQueue("THREADED_JQO"):init()
c.REG=multi:newSystemThreadedTable("THREADED_JQ_F_REG"):init()
-- registerJob(name,func)
-- pushJob(...)
function c:registerJob(name,func)
self.REG[name]=func
end
function c:pushJob(name,...)
self.queueOUT:push({self.jobnum,name,...})
self.jobnum=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
GLOBAL["__JQ_COUNT__"]=c.cores
for i=1,c.cores do
multi:newSystemThread("System Threaded Job Queue Worker Thread #"..i,function()
require("multi")
__sleep__=.001
if love then -- lets make sure we don't reference upvalues if using love2d
GLOBAL=_G.GLOBAL
sThread=_G.sThread
__sleep__=.1
end
JQI=sThread.waitFor("THREADED_JQO"):init() -- Grab it
JQO=sThread.waitFor("THREADED_JQ"):init() -- Grab it
FGLOBAL=sThread.waitFor("THREADED_JQ_F_REG"):init() -- Grab it
sThread.sleep(.1) -- lets wait for things to work out
setmetatable(_G,{
__index=FGLOBAL
})
GLOBAL["THREADED_JQ"]=nil -- remove it
GLOBAL["THREADED_JQO"]=nil -- remove it
GLOBAL["THREADED_JQ_F_REG"]=nil -- remove it
multi:newLoop(function()
sThread.sleep(__sleep__) -- lets allow cpu time for other processes on our system!
local job=JQI:pop()
if job then
local ID=table.remove(job,1) -- return and remove
local name=table.remove(job,1) -- return and remove
local ret={FGLOBAL:waitFor(name)(unpack(job))} -- unpack the rest
JQO:push({ID,ret})
end
end)
multi:mainloop()
end)
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))
end
data=self.link.queueIN:pop()
end
end)
c.updater.link=c
return c
end
if love then
if love.thread then
function multi:newSystemThreadedJobQueue(numOfCores)
local c={}
c.jobnum=1
c.cores=numOfCores or multi.integration.THREAD.getCores()
c.queueIN=multi:newSystemThreadedQueue("THREADED_JQ"):init()
c.queueOUT=multi:newSystemThreadedQueue("THREADED_JQO"):init()
function c:registerJob(name,func)
GLOBAL["__TJQ__"..name.."__"]=func
end
function c:pushJob(name,...)
self.queueOUT:push({self.jobnum,name,...})
self.jobnum=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
GLOBAL["__JQ_COUNT__"]=c.cores
for i=1,c.cores do
multi:newSystemThread("System Threaded Job Queue Worker Thread #"..i,function()
GLOBAL=_G.GLOBAL
sThread=_G.sThread
local JQI=sThread.waitFor("THREADED_JQO"):init() -- Grab it
local JQO=sThread.waitFor("THREADED_JQ"):init() -- Grab it
sThread.sleep(.1) -- lets wait for things to work out
setmetatable(_G,{
__index=function(t,k,v)
return GLOBAL["__TJQ__"..k.."__"]
end
})
GLOBAL["THREADED_JQ"]=nil -- remove it
GLOBAL["THREADED_JQO"]=nil -- remove it
multi:newLoop(function()
local job=JQI:pop()
if job then
local ID=table.remove(job,1) -- return and remove
local name=table.remove(job,1) -- return and remove
local ret={sThread.waitFor("__TJQ__"..name.."__")(unpack(job))} -- unpack the rest
JQO:push({ID,ret})
end
end)
end)
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))
end
data=self.link.queueIN:pop()
end
end)
c.updater.link=c
return c
end
end
end