mirror of
https://github.com/rayaman/multi.git
synced 2026-09-05 07:27:35 -04:00
(1.8.4) Update
This commit is contained in:
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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
|
||||
]]
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user