Working on 16.0.0 #53
15
init.lua
15
init.lua
@ -1630,14 +1630,11 @@ function thread:newThread(name, func, ...)
|
|||||||
|
|
||||||
c.Destroy = c.Kill
|
c.Destroy = c.Kill
|
||||||
if thread.isThread() then
|
if thread.isThread() then
|
||||||
multi:newLoop(function(loop)
|
if self.Type == multi.PROCESS then
|
||||||
if self.Type == multi.PROCESS then
|
table.insert(self.startme, c)
|
||||||
table.insert(self.startme, c)
|
else
|
||||||
else
|
table.insert(threadManager.startme, c)
|
||||||
table.insert(threadManager.startme, c)
|
end
|
||||||
end
|
|
||||||
loop:Break()
|
|
||||||
end)
|
|
||||||
else
|
else
|
||||||
if self.Type == multi.PROCESS then
|
if self.Type == multi.PROCESS then
|
||||||
table.insert(self.startme, c)
|
table.insert(self.startme, c)
|
||||||
@ -2411,8 +2408,8 @@ function multi.error(self, err)
|
|||||||
else
|
else
|
||||||
io.write("\x1b[91mERROR:\x1b[0m " .. err .. " ?\n")
|
io.write("\x1b[91mERROR:\x1b[0m " .. err .. " ?\n")
|
||||||
end
|
end
|
||||||
error("^^^ " .. multi:getCurrentProcess():getFullName() .. " " .. multi:getCurrentTask().Type .. "\n" .. debug.traceback().."\n")
|
|
||||||
if multi.defaultSettings.error then
|
if multi.defaultSettings.error then
|
||||||
|
error("^^^ " .. multi:getCurrentProcess():getFullName() .. " " .. multi:getCurrentTask().Type .. "\n" .. debug.traceback().."\n")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -70,9 +70,8 @@ function multi:newSystemThread(name, func, ...)
|
|||||||
local rand = math.random(1, 10000000)
|
local rand = math.random(1, 10000000)
|
||||||
local return_linda = lanes.linda()
|
local return_linda = lanes.linda()
|
||||||
c = {}
|
c = {}
|
||||||
c.name = name
|
|
||||||
c.Name = name
|
c.Name = name
|
||||||
c.Id = count
|
c.ID = count
|
||||||
c.loadString = {"base","package","os","io","math","table","string","coroutine"}
|
c.loadString = {"base","package","os","io","math","table","string","coroutine"}
|
||||||
livingThreads[count] = {true, name}
|
livingThreads[count] = {true, name}
|
||||||
c.returns = return_linda
|
c.returns = return_linda
|
||||||
@ -162,13 +161,13 @@ function multi.InitSystemThreadErrorHandler()
|
|||||||
for i = #threads, 1, -1 do
|
for i = #threads, 1, -1 do
|
||||||
temp = threads[i]
|
temp = threads[i]
|
||||||
status = temp.thread.status
|
status = temp.thread.status
|
||||||
push = __StatusLinda:get(temp.Id)
|
push = __StatusLinda:get(temp.ID)
|
||||||
if push then
|
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
|
end
|
||||||
if status == "done" or temp.returns:get("returns") then
|
if status == "done" or temp.returns:get("returns") then
|
||||||
returns = ({temp.returns:receive(0, "returns")})[2]
|
returns = ({temp.returns:receive(0, "returns")})[2]
|
||||||
livingThreads[temp.Id] = {false, temp.Name}
|
livingThreads[temp.ID] = {false, temp.Name}
|
||||||
temp.alive = false
|
temp.alive = false
|
||||||
if returns[1] == false then
|
if returns[1] == false then
|
||||||
temp.OnError:Fire(temp, returns[2])
|
temp.OnError:Fire(temp, returns[2])
|
||||||
@ -185,13 +184,13 @@ function multi.InitSystemThreadErrorHandler()
|
|||||||
elseif status == "error" then
|
elseif status == "error" then
|
||||||
-- The thread never really errors, we handle this through our linda object
|
-- The thread never really errors, we handle this through our linda object
|
||||||
elseif status == "cancelled" then
|
elseif status == "cancelled" then
|
||||||
livingThreads[temp.Id] = {false, temp.Name}
|
livingThreads[temp.ID] = {false, temp.Name}
|
||||||
temp.alive = false
|
temp.alive = false
|
||||||
temp.OnError:Fire(temp,"thread_cancelled")
|
temp.OnError:Fire(temp,"thread_cancelled")
|
||||||
GLOBAL["__THREADS__"] = livingThreads
|
GLOBAL["__THREADS__"] = livingThreads
|
||||||
table.remove(threads, i)
|
table.remove(threads, i)
|
||||||
elseif status == "killed" then
|
elseif status == "killed" then
|
||||||
livingThreads[temp.Id] = {false, temp.Name}
|
livingThreads[temp.ID] = {false, temp.Name}
|
||||||
temp.alive = false
|
temp.alive = false
|
||||||
temp.OnError:Fire(temp,"thread_killed")
|
temp.OnError:Fire(temp,"thread_killed")
|
||||||
GLOBAL["__THREADS__"] = livingThreads
|
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()
|
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 {
|
return {
|
||||||
init = function(global_channel, console_channel, status_channel)
|
init = function()
|
||||||
return GLOBAL, THREAD
|
return GLOBAL, THREAD
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,7 +65,7 @@ local function unpackValue(d)
|
|||||||
if not status then
|
if not status then
|
||||||
multi.error(data)
|
multi.error(data)
|
||||||
end
|
end
|
||||||
return serpent.load(data:sub(2,-1))[1]
|
return data[1]
|
||||||
else
|
else
|
||||||
return d
|
return d
|
||||||
end
|
end
|
||||||
@ -101,8 +101,10 @@ local function createTable(n)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function INIT(global_channel, console_channel, status_channel)
|
function INIT()
|
||||||
local GLOBAL, THREAD = createTable("GLOBAL"), {}
|
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
|
-- Non portable methods, shouldn't be used unless you know what you are doing
|
||||||
THREAD.packValue = packValue
|
THREAD.packValue = packValue
|
||||||
@ -117,16 +119,16 @@ function INIT(global_channel, console_channel, status_channel)
|
|||||||
return GLOBAL[name]
|
return GLOBAL[name]
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.waitFor(name)
|
THREAD.waitFor = thread:newFunction(function(name)
|
||||||
local function wait()
|
local function wait()
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
love.timer.sleep(.001)
|
thread.yield()
|
||||||
end
|
end
|
||||||
repeat
|
repeat
|
||||||
wait()
|
wait()
|
||||||
until GLOBAL[name]
|
until GLOBAL[name]
|
||||||
return GLOBAL[name]
|
return GLOBAL[name]
|
||||||
end
|
end, true)
|
||||||
|
|
||||||
function THREAD.getCores()
|
function THREAD.getCores()
|
||||||
return love.system.getProcessorCount()
|
return love.system.getProcessorCount()
|
||||||
@ -154,18 +156,16 @@ function INIT(global_channel, console_channel, status_channel)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.pushStatus(...)
|
function THREAD.pushStatus(...)
|
||||||
status_channel:push({THREAD_ID, multi.pack(...)})
|
status_channel:push(multi.pack(...))
|
||||||
end
|
end
|
||||||
|
|
||||||
_G.THREAD_ID = 0
|
|
||||||
|
|
||||||
function THREAD.sleep(n)
|
function THREAD.sleep(n)
|
||||||
love.timer.sleep(n)
|
love.timer.sleep(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.hold(n)
|
THREAD.hold = thread:newFunction(function(n)
|
||||||
--
|
thread.hold(n)
|
||||||
end
|
end, true)
|
||||||
|
|
||||||
function THREAD.setENV(env, name)
|
function THREAD.setENV(env, name)
|
||||||
GLOBAL[name or "__env"] = env
|
GLOBAL[name or "__env"] = env
|
||||||
@ -187,8 +187,7 @@ function INIT(global_channel, console_channel, status_channel)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
-- These are the acutal channels
|
init = function()
|
||||||
init = function(global_channel, console_channel, status_channel)
|
return INIT()
|
||||||
return INIT(global_channel, console_channel, status_channel)
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package.path = "../?/init.lua;../?.lua;"..package.path
|
package.path = "../?/init.lua;../?.lua;"..package.path
|
||||||
local multi, thread = require("multi"):init()
|
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}
|
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
|
if type(v) == "function" then v() end
|
||||||
end
|
end
|
||||||
|
|
||||||
multi:newAlarm(3):OnRing(function()
|
local test = multi:newSystemThread("Test",function()
|
||||||
GLOBAL["Test2"] = "We got a value!"
|
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)
|
end)
|
||||||
|
|
||||||
thread:newThread(function()
|
thread:newThread(function()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user