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