Rewriting love2d threading binding
This commit is contained in:
parent
e43fe34a7c
commit
afdd98ab13
15
init.lua
15
init.lua
@ -1630,14 +1630,11 @@ function thread:newThread(name, func, ...)
|
||||
|
||||
c.Destroy = c.Kill
|
||||
if thread.isThread() then
|
||||
multi:newLoop(function(loop)
|
||||
if self.Type == multi.PROCESS then
|
||||
table.insert(self.startme, c)
|
||||
else
|
||||
table.insert(threadManager.startme, c)
|
||||
end
|
||||
loop:Break()
|
||||
end)
|
||||
if self.Type == multi.PROCESS then
|
||||
table.insert(self.startme, c)
|
||||
else
|
||||
table.insert(threadManager.startme, c)
|
||||
end
|
||||
else
|
||||
if self.Type == multi.PROCESS then
|
||||
table.insert(self.startme, c)
|
||||
@ -2411,8 +2408,8 @@ function multi.error(self, err)
|
||||
else
|
||||
io.write("\x1b[91mERROR:\x1b[0m " .. err .. " ?\n")
|
||||
end
|
||||
error("^^^ " .. multi:getCurrentProcess():getFullName() .. " " .. multi:getCurrentTask().Type .. "\n" .. debug.traceback().."\n")
|
||||
if multi.defaultSettings.error then
|
||||
error("^^^ " .. multi:getCurrentProcess():getFullName() .. " " .. multi:getCurrentTask().Type .. "\n" .. debug.traceback().."\n")
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
@ -70,9 +70,8 @@ function multi:newSystemThread(name, func, ...)
|
||||
local rand = math.random(1, 10000000)
|
||||
local return_linda = lanes.linda()
|
||||
c = {}
|
||||
c.name = name
|
||||
c.Name = name
|
||||
c.Id = count
|
||||
c.ID = count
|
||||
c.loadString = {"base","package","os","io","math","table","string","coroutine"}
|
||||
livingThreads[count] = {true, name}
|
||||
c.returns = return_linda
|
||||
@ -162,13 +161,13 @@ function multi.InitSystemThreadErrorHandler()
|
||||
for i = #threads, 1, -1 do
|
||||
temp = threads[i]
|
||||
status = temp.thread.status
|
||||
push = __StatusLinda:get(temp.Id)
|
||||
push = __StatusLinda:get(temp.ID)
|
||||
if push then
|
||||
temp.statusconnector:Fire(multi.unpack(({__StatusLinda:receive(nil, temp.Id)})[2]))
|
||||
temp.statusconnector:Fire(multi.unpack(({__StatusLinda:receive(nil, temp.ID)})[2]))
|
||||
end
|
||||
if status == "done" or temp.returns:get("returns") then
|
||||
returns = ({temp.returns:receive(0, "returns")})[2]
|
||||
livingThreads[temp.Id] = {false, temp.Name}
|
||||
livingThreads[temp.ID] = {false, temp.Name}
|
||||
temp.alive = false
|
||||
if returns[1] == false then
|
||||
temp.OnError:Fire(temp, returns[2])
|
||||
@ -185,13 +184,13 @@ function multi.InitSystemThreadErrorHandler()
|
||||
elseif status == "error" then
|
||||
-- The thread never really errors, we handle this through our linda object
|
||||
elseif status == "cancelled" then
|
||||
livingThreads[temp.Id] = {false, temp.Name}
|
||||
livingThreads[temp.ID] = {false, temp.Name}
|
||||
temp.alive = false
|
||||
temp.OnError:Fire(temp,"thread_cancelled")
|
||||
GLOBAL["__THREADS__"] = livingThreads
|
||||
table.remove(threads, i)
|
||||
elseif status == "killed" then
|
||||
livingThreads[temp.Id] = {false, temp.Name}
|
||||
livingThreads[temp.ID] = {false, temp.Name}
|
||||
temp.alive = false
|
||||
temp.OnError:Fire(temp,"thread_killed")
|
||||
GLOBAL["__THREADS__"] = livingThreads
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package.path = "../?/init.lua;../?.lua;"..package.path
|
||||
local multi, thread = require("multi"):init()
|
||||
|
||||
local GLOBAL, THREAD = require("multi.integration.loveManager"):init()
|
||||
GLOBAL, THREAD = require("multi.integration.loveManager"):init()
|
||||
|
||||
GLOBAL["Test"] = {1,2,3, function() print("HI") end}
|
||||
|
||||
@ -10,8 +10,28 @@ for i,v in pairs(GLOBAL["Test"]) do
|
||||
if type(v) == "function" then v() end
|
||||
end
|
||||
|
||||
multi:newAlarm(3):OnRing(function()
|
||||
GLOBAL["Test2"] = "We got a value!"
|
||||
local test = multi:newSystemThread("Test",function()
|
||||
print("THREAD_ID:",THREAD_ID)
|
||||
GLOBAL["Test2"] = "We did it!"
|
||||
eror("hahaha")
|
||||
return 1,2,3
|
||||
end)
|
||||
|
||||
test.OnDeath(function(a,b,c)
|
||||
print("Thread finished!",a,b,c)
|
||||
end)
|
||||
|
||||
test.OnError(function(self, err)
|
||||
print("Got Error!",err)
|
||||
end)
|
||||
|
||||
local func = THREAD:newFunction(function(a,b,c)
|
||||
print("let's do this!",1,2,3)
|
||||
return true
|
||||
end)
|
||||
|
||||
func(1,2,3).OnReturn(function(ret)
|
||||
print("Done",ret)
|
||||
end)
|
||||
|
||||
thread:newThread(function()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user