From d7978753175cc1b5f09150042c838a8f276f500c Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Sat, 8 Feb 2020 11:04:05 -0500 Subject: [PATCH] added THREAD:newFunction(func) --- changes.md | 17 ++++++++++++-- multi/compat/love2d.lua | 14 ++++++++++++ multi/integration/lanesManager/init.lua | 22 +++++++++++++----- multi/integration/loveManager/extensions.lua | 8 +------ multi/integration/loveManager/init.lua | 24 ++++++++++++++++++-- 5 files changed, 68 insertions(+), 17 deletions(-) diff --git a/changes.md b/changes.md index e765182..2a78aeb 100644 --- a/changes.md +++ b/changes.md @@ -6,6 +6,15 @@ Update 14.1.0 Bug Fixes and a change ```lua package.path="?/init.lua;?.lua;"..package.path multi,thread = require("multi"):init() +local GLOBAL, THREAD = require("multi.integration.lanesManager"):init() +t = THREAD:newFunction(function(...) + print("This is a system threaded function!",...) + THREAD.sleep(1) -- This is handled within a system thread! Note: this creates a system thread that runs then ends. C + return "We done!" +end) +print(t("hehe",1,2,3,true).connect(function(...) + print("connected:",...) +end)) -- The same features that work with thread:newFunction() are here as well multi.OnLoad(function() print("Code Loaded!") -- Connect to the load event end) @@ -68,11 +77,13 @@ end) multi:mainloop() ``` # Changed: -- thread:newFunction(func,holdme) -- Added an argument holdme to always force the threaded funcion to wait. Meaning you don't need to tell it to func().wait() or func().connect() +- thread:newFunction(func,holup) -- Added an argument holdme to always force the threaded funcion to wait. Meaning you don't need to tell it to func().wait() or func().connect() - multi:newConnection(protect,callback,kill) -- Added the kill argument. Makes connections work sort of like a stack. Pop off the connections as they get called. So a one time connection handler. - I'm not sure callback has been documented in any form. callback gets called each and everytime conn:Fire() gets called! As well as being triggered for each connfunc that is part of the connection. -# Added: +# Added: +- THREAD:newFunction(func,holup) -- A system threaded based variant to thread:newFunction(func,holup) +- multi:loveloop() -- Handles the run function for love2d as well as run the multi mainloop. - multi.OnLoad(func) -- A special connection that allows you to connect to the an event that triggers when the multi engine starts! This is slightly different from multi.PreLoad(func) Which connects before any variables have been set up in the multi table, before any settings are cemented into the core. In most cases they will operate exactly the same. This is a feature that was created with module creators in mind. This way they can have code be loaded and managed before the main loop starts. - multi.OnExit(func) -- A special connection that allows you to connect onto the lua state closing event. ```lua @@ -136,6 +147,8 @@ multi:mainloop() # Removed: - multi:newTimeStamper() -- schedulejob replaces timestamper # Fixed: +- love2d had an issue where threads crashing would break the mainloop +- fixed bugs within the extensions.lua file for love threading - Modified the thread.* methods to perform better (Tables were being created each time one of these methods were called! Which in turn slowed things down. One table is modified to get things working properly) - thread.sleep() - thread.hold() diff --git a/multi/compat/love2d.lua b/multi/compat/love2d.lua index a5b0463..62cfc86 100644 --- a/multi/compat/love2d.lua +++ b/multi/compat/love2d.lua @@ -69,6 +69,20 @@ multi.OnPreLoad(function() end end) end) + +function multi:loveloop() + local link + link = multi:newThread(function() + local mainloop = love.run() + while true do + thread.yield() + pcall(mainloop) + end + end).OnError(function(...) + print(...) + end) + multi:mainloop() +end multi.OnQuit(function() multi.Stop() love.event.quit() diff --git a/multi/integration/lanesManager/init.lua b/multi/integration/lanesManager/init.lua index 7d43008..fd7ba3b 100644 --- a/multi/integration/lanesManager/init.lua +++ b/multi/integration/lanesManager/init.lua @@ -48,6 +48,18 @@ local threads = {} local count = 1 local started = false local livingThreads = {} +function THREAD:newFunction(func,holup) + return function(...) + local t = multi:newSystemThread("SystemThreadedFunction",function(...) + return func(...) + end,...) + return thread:newFunction(function() + return thread.hold(function() + return t.thread:join(.001) + end) + end,holup)() + end +end function multi:newSystemThread(name, func, ...) multi.InitSystemThreadErrorHandler() rand = math.random(1, 10000000) @@ -63,12 +75,10 @@ function multi:newSystemThread(name, func, ...) c.alive = true c.priority = thread.Priority_Normal local args = {...} - multi.nextStep(function() - c.thread = lanes.gen(table.concat(c.loadString,","),{globals={ - THREAD_NAME=name, - THREAD_ID=count - },priority=c.priority}, func)(unpack(args)) - end) + c.thread = lanes.gen(table.concat(c.loadString,","),{globals={ + THREAD_NAME=name, + THREAD_ID=count + },priority=c.priority}, func)(unpack(args)) count = count + 1 function c:kill() self.thread:cancel() diff --git a/multi/integration/loveManager/extensions.lua b/multi/integration/loveManager/extensions.lua index 2e6f091..aeb3b2d 100644 --- a/multi/integration/loveManager/extensions.lua +++ b/multi/integration/loveManager/extensions.lua @@ -22,7 +22,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] local multi, thread = require("multi").init() -local pad = require("multi.integration.loveManager.scratchpad") GLOBAL = multi.integration.GLOBAL THREAD = multi.integration.THREAD function multi:newSystemThreadedQueue(name) @@ -82,11 +81,8 @@ function multi:newSystemThreadedJobQueue(n) c.queueAll = love.thread.getChannel("__JobQueue_"..jqc.."_queueAll") c.id = 0 c.OnJobCompleted = multi:newConnection() - c._bytedata = love.data.newByteData(string.rep(status.BUSY,c.cores)) - c.bytedata = pad:new(c._bytedata) local allfunc = 0 function c:doToAll(func) - self.bytedata:write(string.rep(status.BUSY,c.cores)) -- set all variables to busy local f = THREAD.dump(func) for i = 1, self.cores do self.queueAll:push({allfunc,f}) @@ -97,7 +93,6 @@ function multi:newSystemThreadedJobQueue(n) if self.funcs[name] then error("A function by the name "..name.." has already been registered!") end - self.bytedata:write(string.rep(status.BUSY,c.cores)) -- set all variables to busy self.funcs[name] = func end function c:pushJob(name,...) @@ -115,6 +110,7 @@ function multi:newSystemThreadedJobQueue(n) end end end) + print("Cores: ",c.cores) for i=1,c.cores do multi:newSystemThread("JobQueue_"..jqc.."_worker_"..i,function(jqc) local multi, thread = require("multi"):init() @@ -123,8 +119,6 @@ function multi:newSystemThreadedJobQueue(n) end require("love.timer") local clock = os.clock - local pad = require("multi.integration.loveManager.scratchpad") - local status = require("multi.integration.loveManager.status") local funcs = THREAD.createStaticTable("__JobQueue_"..jqc.."_table") local queue = love.thread.getChannel("__JobQueue_"..jqc.."_queue") local queueReturn = love.thread.getChannel("__JobQueue_"..jqc.."_queueReturn") diff --git a/multi/integration/loveManager/init.lua b/multi/integration/loveManager/init.lua index a59369a..9097609 100644 --- a/multi/integration/loveManager/init.lua +++ b/multi/integration/loveManager/init.lua @@ -27,14 +27,16 @@ end local ThreadFileData = [[ ISTHREAD = true THREAD = require("multi.integration.loveManager.threads") -- order is important! -STATUS = require("multi.integration.loveManager.status") +sThread = THREAD __IMPORTS = {...} __FUNC__=table.remove(__IMPORTS,1) __THREADID__=table.remove(__IMPORTS,1) __THREADNAME__=table.remove(__IMPORTS,1) +stab = THREAD.createStaticTable(__THREADNAME__) GLOBAL = THREAD.getGlobal() multi, thread = require("multi").init() -THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))]] +stab["returns"] = {THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))} +]] local multi, thread = require("multi.compat.love2d"):init() local THREAD = {} __THREADID__ = 0 @@ -45,18 +47,36 @@ local THREAD = require("multi.integration.loveManager.threads") local GLOBAL = THREAD.getGlobal() local THREAD_ID = 1 local OBJECT_ID = 0 +function THREAD:newFunction(func,holup) + return function(...) + local t = multi:newSystemThread("SystemThreadedFunction",func,...) + return thread:newFunction(function() + return thread.hold(function() + if t.stab["returns"] then + return unpack(t.stab.returns) + end + end) + end,holup)() + end +end function multi:newSystemThread(name,func,...) local c = {} c.name = name c.ID=THREAD_ID c.thread=love.thread.newThread(ThreadFileData) c.thread:start(THREAD.dump(func),c.ID,c.name,...) + c.stab = THREAD.createStaticTable(name) GLOBAL["__THREAD_"..c.ID] = {ID=c.ID,Name=c.name,Thread=c.thread} GLOBAL["__THREAD_COUNT"] = THREAD_ID THREAD_ID=THREAD_ID+1 + return c +end +function love.threaderror(thread, errorstr) + print("Thread error!\n"..errorstr) end multi.integration.GLOBAL = GLOBAL multi.integration.THREAD = THREAD +require("multi.integration.loveManager.extensions") return {init=function() return GLOBAL,THREAD end} \ No newline at end of file