Rewriting love2d threading binding

This commit is contained in:
2023-07-15 01:16:03 -04:00
parent e43fe34a7c
commit afdd98ab13
5 changed files with 164 additions and 35 deletions
+115 -1
View File
@@ -1,8 +1,122 @@
if ISTHREAD then
error("You cannot require the loveManager from within a thread!")
end
local ThreadFileData = [[
ISTHREAD = true
__FUNC, THREAD_ID, THREAD_NAME, __PACK = ...
GLOBAL, THREAD = require("multi.integration.loveManager.threads"):init()
__FUNC = THREAD.unpackValue(__FUNC)
__PACK = THREAD.unpackValue(__PACK)
math.randomseed(THREAD_ID)
math.random()
math.random()
math.random()
stab = THREAD.createTable(THREAD_NAME .. THREAD_ID)
if GLOBAL["__env"] then
local env = THREAD.unpackENV(GLOBAL["__env"])
for i,v in pairs(env) do
_G[i] = v
end
end
multi, thread = require("multi"):init()
require("multi.integration.loveManager.extensions")
require("multi.integration.sharedExtensions")
stab["returns"] = {__FUNC(multi.unpack(__PACK))}
]]
_G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0
local multi, thread = require("multi"):init()
local GLOBAL, THREAD = require("multi.integration.loveManager.threads"):init()
multi.integration = {}
multi.isMainThread = true
local threads = {}
local tid = 0
function multi:newSystemThread(name, func, ...)
multi.InitSystemThreadErrorHandler()
local name = name or multi.randomString(16)
tid = tid + 1
local c = {}
c.Type = multi.STHREAD
c.Name = name
c.ID = tid
c.thread = love.thread.newThread(ThreadFileData)
c.thread:start(THREAD.packValue(func), c.ID, c.Name, THREAD.packValue({...}))
c.stab = THREAD.createTable(name .. c.ID)
c.creationTime = os.clock()
c.OnDeath = multi:newConnection()
c.OnError = multi:newConnection()
c.status_channel = love.thread.getChannel("__status_channel__" .. c.ID)
function c:getName() return c.name end
table.insert(threads, c)
if self.isActor then
self:create(c)
else
multi.create(multi, c)
end
return c
end
local started = false
local console_channel = love.thread.getChannel("__console_channel__")
function THREAD:newFunction(func, holdme)
return thread:newFunctionBase(function(...)
return multi:newSystemThread("SystemThreaded Function Handler", func, ...)
end, holdme, multi.SFUNCTION)()
end
function love.threaderror(thread, errorstr)
multi.error("Thread error! " .. errorstr)
end
function multi.InitSystemThreadErrorHandler()
if started == true then return end
started = true
thread:newThread("Love System Thread Handler", function()
while true do
thread.yield()
for i = #threads, 1, -1 do
local th = threads[i]
if th.status_channel:peek() ~= nil then
th.statusconnector:Fire(multi.unpack(th.status_channel:pop()))
end
local th_err = th.thread:getError()
if th_err == "Thread Killed!\1" then
th.OnDeath:Fire("Thread Killed!")
table.remove(threads, i)
elseif th_err then
th.OnError:Fire(th, th_err)
table.remove(threads, i)
elseif th.stab.returns then
th.OnDeath:Fire(multi.unpack(th.stab.returns))
th.stab.returns = nil
table.remove(threads, i)
end
end
end
end)
end
THREAD.newSystemThread = function(...)
multi:newSystemThread(...)
end
multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD
require("multi.integration.loveManager.extensions")
require("multi.integration.sharedExtensions")
multi.print("Integrated Love Threading!")
return {
init = function(global_channel, console_channel, status_channel)
init = function()
return GLOBAL, THREAD
end
}
+14 -15
View File
@@ -65,7 +65,7 @@ local function unpackValue(d)
if not status then
multi.error(data)
end
return serpent.load(data:sub(2,-1))[1]
return data[1]
else
return d
end
@@ -101,8 +101,10 @@ local function createTable(n)
)
end
function INIT(global_channel, console_channel, status_channel)
local GLOBAL, THREAD = createTable("GLOBAL"), {}
function INIT()
local GLOBAL, THREAD = createTable("__GLOBAL__"), {}
local status_channel, console_channel = love.thread.getChannel("__status_channel__" .. THREAD_ID),
love.thread.getChannel("__console_channel__")
-- Non portable methods, shouldn't be used unless you know what you are doing
THREAD.packValue = packValue
@@ -117,16 +119,16 @@ function INIT(global_channel, console_channel, status_channel)
return GLOBAL[name]
end
function THREAD.waitFor(name)
THREAD.waitFor = thread:newFunction(function(name)
local function wait()
math.randomseed(os.time())
love.timer.sleep(.001)
thread.yield()
end
repeat
wait()
until GLOBAL[name]
return GLOBAL[name]
end
end, true)
function THREAD.getCores()
return love.system.getProcessorCount()
@@ -154,18 +156,16 @@ function INIT(global_channel, console_channel, status_channel)
end
function THREAD.pushStatus(...)
status_channel:push({THREAD_ID, multi.pack(...)})
status_channel:push(multi.pack(...))
end
_G.THREAD_ID = 0
function THREAD.sleep(n)
love.timer.sleep(n)
end
function THREAD.hold(n)
--
end
THREAD.hold = thread:newFunction(function(n)
thread.hold(n)
end, true)
function THREAD.setENV(env, name)
GLOBAL[name or "__env"] = env
@@ -187,8 +187,7 @@ function INIT(global_channel, console_channel, status_channel)
end
return {
-- These are the acutal channels
init = function(global_channel, console_channel, status_channel)
return INIT(global_channel, console_channel, status_channel)
init = function()
return INIT()
end
}