diff --git a/changes.md b/changes.md index c60a72e..f792de7 100644 --- a/changes.md +++ b/changes.md @@ -21,6 +21,14 @@ Added: - special variable multi.NIL was added to allow error handling in threaded functions. -- multi.NIL can be used in to force a nil value when using thread.hold() - All functions created in the root of a thread are now converted to threaded functions, which allow for wait and connect features. **Note:** these functions are local to the function! And are only converted if they aren't set as local! Otherwise the function +- lanes threads can now have their priority set using: sThread.priority = +-- thread.Priority_Core +-- thread.Priority_High +-- thread.Priority_Above_Normal +-- thread.Priority_Normal +-- thread.Priority_Below_Normal +-- thread.Priority_Low +-- thread.Priority_Idle thread newFunction ```lua @@ -78,6 +86,8 @@ Changed: ```lua local multi, thread = require("multi").init() -- The require multi function still returns the multi object like before ``` +- love/lanesManager system threading integration has been reworked. Faster and cleaner code! Consistant code as well +- l Note: Using init allows you to get access to the thread handle. This was done because thread was modifying the global space as well as multi. I wanted to not modify the global space anymore. internally most of your code can stay the same, you only need to change how the library is required. I do toy a bit with the global space, buy I use a variable name that is invalid as a variable name. The variable name is $multi. This is used internally to keep some records and maintain a clean space diff --git a/multi/compat/love2d.lua b/multi/compat/love2d.lua index 8557c4c..fa506c6 100644 --- a/multi/compat/love2d.lua +++ b/multi/compat/love2d.lua @@ -38,48 +38,39 @@ multi.OnDraw = multi:newConnection() multi.OnTextInput = multi:newConnection() multi.OnUpdate = multi:newConnection() multi.OnQuit = multi:newConnection() -multi.OnPreLoad( - function() - local function Hook(func, conn) - if love[func] ~= nil then - love[func] = Library.convert(love[func]) - love[func]:inject( - function(...) - conn:Fire(...) - return {...} - end, - 1 - ) - elseif love[func] == nil then - love[func] = function(...) - conn:Fire(...) - end +multi.OnPreLoad(function() + local function Hook(func, conn) + if love[func] ~= nil then + love[func] = Library.convert(love[func]) + love[func]:inject(function(...) + conn:Fire(...) + return {...} + end,1) + elseif love[func] == nil then + love[func] = function(...) + conn:Fire(...) end end - Hook("quit", multi.OnQuit) - Hook("keypressed", multi.OnKeyPressed) - Hook("keyreleased", multi.OnKeyReleased) - Hook("mousepressed", multi.OnMousePressed) - Hook("mousereleased", multi.OnMouseReleased) - Hook("wheelmoved", multi.OnMouseWheelMoved) - Hook("mousemoved", multi.OnMouseMoved) - Hook("draw", multi.OnDraw) - Hook("textinput", multi.OnTextInput) - Hook("update", multi.OnUpdate) - multi.OnDraw( - function() - for i = 1, #multi.drawF do - love.graphics.setColor(255, 255, 255, 255) - multi.drawF[i]() - end - end - ) end -) -multi.OnQuit( - function() - multi.Stop() - love.event.quit() - end -) + Hook("quit", multi.OnQuit) + Hook("keypressed", multi.OnKeyPressed) + Hook("keyreleased", multi.OnKeyReleased) + Hook("mousepressed", multi.OnMousePressed) + Hook("mousereleased", multi.OnMouseReleased) + Hook("wheelmoved", multi.OnMouseWheelMoved) + Hook("mousemoved", multi.OnMouseMoved) + Hook("draw", multi.OnDraw) + Hook("textinput", multi.OnTextInput) + Hook("update", multi.OnUpdate) + multi.OnDraw(function() + for i = 1, #multi.drawF do + love.graphics.setColor(255, 255, 255, 255) + multi.drawF[i]() + end + end) +end) +multi.OnQuit(function() + multi.Stop() + love.event.quit() +end) return multi diff --git a/multi/compat/scratchpad.lua b/multi/compat/scratchpad.lua deleted file mode 100644 index 9a8619d..0000000 --- a/multi/compat/scratchpad.lua +++ /dev/null @@ -1,39 +0,0 @@ ---local test = love.newByteData(string.rep("\0",16) -local ffi = require("ffi") -local scratchpad = {} -local mt = { - __index = function(t, k) - if type(k)=="string" then - local a, b = k:match("(%d+):(%d+)") - return t:read(tonumber(a),tonumber(b)) - elseif type(k)=="number" then - return t:read(k,1) - end - end, - __newindex = function(t, k, v) - t:write(v,k) - end -} -function scratchpad:new(data, size, rep) - local c = {} - local pad - if type(data)=="string" then - pad = love.data.newByteData(data or string.rep(rep or "\0",size or 16)) - elseif data:type()=="ByteData" then - pad = bytedata - end - local ptr = ffi.cast("unsigned char*",pad:getPointer()) - local size = pad:getSize() - function c:write(data, loc, len) - if loc+(len or #data)>size then - error("Attpemting to write data outside the bounds of data byte array!") - end - ffi.copy(ptr+(loc or 0), data, len or #data) - end - function c:read(loc, len) - return ffi.string(ptr+(loc or 0), len or size) - end - setmetatable(c,mt) - return c -end -return scratchpad \ No newline at end of file diff --git a/multi/init.lua b/multi/init.lua index 998157e..2546115 100644 --- a/multi/init.lua +++ b/multi/init.lua @@ -66,6 +66,13 @@ multi.Priority_Normal = 64 multi.Priority_Below_Normal = 256 multi.Priority_Low = 1024 multi.Priority_Idle = 4096 +thread.Priority_Core = 3 +thread.Priority_High = 2 +thread.Priority_Above_Normal = 1 +thread.Priority_Normal = 0 +thread.Priority_Below_Normal = -1 +thread.Priority_Low = -2 +thread.Priority_Idle = -3 multi.PriorityResolve = { [1]="Core", [4]="High", @@ -831,6 +838,7 @@ function multi:newConnection(protect,func) if self.lock then return end for i=#self.func,1,-1 do if self.protect then + if not self.func[i] then return end local temp={pcall(self.func[i][1],...)} if temp[1] then table.remove(temp,1) @@ -839,6 +847,7 @@ function multi:newConnection(protect,func) multi.print(temp[2]) end else + if not self.func[i] then return end table.insert(ret,{self.func[i][1](...)}) end end diff --git a/multi/integration/code.code-workspace b/multi/integration/code.code-workspace new file mode 100644 index 0000000..8f77322 --- /dev/null +++ b/multi/integration/code.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "C:\\Users\\Ryan\\Desktop\\Code Tests" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/multi/integration/lanesManager/extensions.lua b/multi/integration/lanesManager/extensions.lua new file mode 100644 index 0000000..60ac2ce --- /dev/null +++ b/multi/integration/lanesManager/extensions.lua @@ -0,0 +1,116 @@ +local multi, thread = require("multi"):init() +local GLOBAL, THREAD = multi.integration.GLOBAL,multi.integration.THREAD +function multi:newSystemThreadedQueue(name) + local c = {} + c.linda = lanes.linda() + function c:push(v) + self.linda:send("Q", v) + end + function c:pop() + return ({self.linda:receive(0, "Q")})[2] + end + function c:peek() + return self.linda:get("Q") + end + function c:init() + return self + end + GLOBAL[name or "_"] = c + return c +end +function multi:newSystemThreadedTable(name) + local c = {} + c.link = lanes.linda() + setmetatable(c,{ + __index = function(t,k) + return c.link:get(k) + end, + __newindex = function(t,k,v) + c.link:set(k,v) + end + }) + function c:init() + return self + end + GLOBAL[name or "_"] = c + return c +end +function multi:newSystemThreadedJobQueue(n) + local c = {} + c.cores = n or THREAD.getCores()*2 + c.OnJobCompleted = multi:newConnection() + local funcs = multi:newSystemThreadedTable() + local queueJob = multi:newSystemThreadedQueue() + local queueReturn = multi:newSystemThreadedQueue() + local doAll = multi:newSystemThreadedQueue() + local ID=1 + local jid = 1 + function c:doToAll(func) + for i=1,c.cores do + doAll:push{ID,func} + end + ID = ID + 1 + end + function c:registerFunction(name,func) + funcs[name]=func + end + function c:pushJob(name,...) + queueJob:push{name,jid,{...}} + jid = jid + 1 + end + multi:newThread("JobQueueManager",function() + while true do + local job = thread.hold(function() + return queueReturn:pop() + end) + local id = table.remove(job,1) + c.OnJobCompleted:Fire(id,unpack(job)) + end + end) + for i=1,c.cores do + multi:newSystemThread("SystemThreadedJobQueue",function(queue) + local multi,thread = require("multi"):init() + local idle = os.clock() + local clock = os.clock + local ref = 0 + setmetatable(_G,{__index = funcs}) + multi:newThread("JobHandler",function() + while true do + local dat = thread.hold(function() + return queueJob:pop() + end) + idle = clock() + local name = table.remove(dat,1) + local jid = table.remove(dat,1) + local args = table.remove(dat,1) + queueReturn:push{jid, funcs[name](unpack(args)),queue} + end + end) + multi:newThread("DoAllHandler",function() + while true do + local dat = thread.hold(function() + return doAll:peek() + end) + if dat then + if dat[1]>ref then + idle = clock() + ref = dat[1] + dat[2]() + doAll:pop() + end + end + end + end) + multi:newThread("IdleHandler",function() + while true do + thread.hold(function() + return clock()-idle>3 + end) + THREAD.sleep(.01) + end + end) + multi:mainloop() + end,i).priority = thread.Priority_Core + end + return c +end \ No newline at end of file diff --git a/multi/integration/lanesManager.lua b/multi/integration/lanesManager/init.lua similarity index 83% rename from multi/integration/lanesManager.lua rename to multi/integration/lanesManager/init.lua index c02c788..e82bd32 100644 --- a/multi/integration/lanesManager.lua +++ b/multi/integration/lanesManager/init.lua @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] package.path = "?/init.lua;?.lua;" .. package.path -local multi, thread = require("multi").init() -- get it all and have it on all lanes +multi, thread = require("multi").init() -- get it all and have it on all lanes if multi.integration then -- This allows us to call the lanes manager from supporting modules without a hassel return { init = function() @@ -73,70 +73,7 @@ function THREAD.get(name) end local function randomString(n) local str = "" - local strings = { - "a", - "b", - "c", - "d", - "e", - "f", - "g", - "h", - "i", - "j", - "k", - "l", - "m", - "n", - "o", - "p", - "q", - "r", - "s", - "t", - "u", - "v", - "w", - "x", - "y", - "z", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "0", - "A", - "B", - "C", - "D", - "E", - "F", - "G", - "H", - "I", - "J", - "K", - "L", - "M", - "N", - "O", - "P", - "Q", - "R", - "S", - "T", - "U", - "V", - "W", - "X", - "Y", - "Z" - } + local strings = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","1","2","3","4","5","6","7","8","9","0","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"} for i = 1, n do str = str .. "" .. strings[math.random(1, #strings)] end @@ -198,6 +135,29 @@ local threads = {} local count = 1 local started = false local livingThreads = {} +function multi.removeUpvalues(func) + if not debug then return end + local count=1 + local dat = true + while dat do + dat = debug.setupvalue(func, count, nil) + count = count+1 + end +end +function multi.getUpvalues(func) + local count=1 + local tab = {} + local dat = true + while dat do + dat = debug.getupvalue(func, count) + if dat then + table.insert(tab,dat) + print(dat) + end + count = count+1 + end + return tab +end function multi:newSystemThread(name, func, ...) multi.InitSystemThreadErrorHandler() rand = math.random(1, 10000000) @@ -206,25 +166,20 @@ function multi:newSystemThread(name, func, ...) c.name = name c.Name = name c.Id = count + c.loadString = {"base","package","os,math","table","string","coroutine"} livingThreads[count] = {true, name} - local THREAD_ID = count - count = count + 1 c.Type = "sthread" c.creationTime = os.clock() c.alive = true - local THREAD_NAME = name - local function func2(...) - local multi = require("multi") - _G["THREAD_NAME"] = THREAD_NAME - _G["THREAD_ID"] = THREAD_ID - math.randomseed(rand) - func(...) - if _G.__Needs_Multi then - multi:mainloop() - end - THREAD.kill() - end - c.thread = lanes.gen("*", func2)(...) + 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) + count = count + 1 function c:kill() self.thread:cancel() multi.print("Thread: '" .. self.name .. "' has been stopped!") @@ -242,7 +197,7 @@ function multi.InitSystemThreadErrorHandler() end started = true multi:newThread( - "ThreadErrorHandler", +"ThreadErrorHandler", function() local threads = multi.SystemThreads while true do @@ -276,7 +231,7 @@ multi.print("Integrated Lanes!") multi.integration = {} -- for module creators multi.integration.GLOBAL = GLOBAL multi.integration.THREAD = THREAD -require("multi.integration.shared") +require("multi.integration.lanesManager.extensions") return { init = function() return GLOBAL, THREAD diff --git a/multi/integration/lanesManager/threads.lua b/multi/integration/lanesManager/threads.lua new file mode 100644 index 0000000..ec7c437 --- /dev/null +++ b/multi/integration/lanesManager/threads.lua @@ -0,0 +1,72 @@ +local function INIT(__GlobalLinda,__SleepingLinda) + local THREAD = {} + function THREAD.set(name, val) + __GlobalLinda:set(name, val) + end + function THREAD.get(name) + __GlobalLinda:get(name) + end + function THREAD.waitFor(name) + local function wait() + math.randomseed(os.time()) + __SleepingLinda:receive(.001, "__non_existing_variable") + end + repeat + wait() + until __GlobalLinda:get(name) + return __GlobalLinda:get(name) + end + function THREAD.testFor(name, val, sym) + -- + end + function THREAD.getCores() + return THREAD.__CORES + end + function THREAD.getThreads() + return GLOBAL.__THREADS__ + end + if os.getOS() == "windows" then + THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) + else + THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) + end + function THREAD.kill() -- trigger the lane destruction + error("Thread was killed!") + end + function THREAD.getName() + return THREAD_NAME + end + function THREAD.getID() + return THREAD_ID + end + _G.THREAD_ID = 0 + function THREAD.sleep(n) + math.randomseed(os.time()) + __SleepingLinda:receive(n, "__non_existing_variable") + end + function THREAD.hold(n) + local function wait() + math.randomseed(os.time()) + __SleepingLinda:receive(.001, "__non_existing_variable") + end + repeat + wait() + until n() + end + local GLOBAL = {} + setmetatable(GLOBAL, { + __index = function(t, k) + return __GlobalLinda:get(k) + end, + __newindex = function(t, k, v) + for i,v in pairs(__GlobalLinda) do + print(i,v) + end + __GlobalLinda:set(k, v) + end + }) + return GLOBAL, THREAD +end +return {init = function(g,s) + return INIT(g,s) +end} \ No newline at end of file diff --git a/multi/integration/loveManager.lua b/multi/integration/loveManager.lua deleted file mode 100644 index 8c74f47..0000000 --- a/multi/integration/loveManager.lua +++ /dev/null @@ -1,523 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2019 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sub-license, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -local multi = require("multi.compat.love2d") -if multi.integration then -- This allows us to call the lanes manager from supporting modules without a hassel - return { - init = function() - return multi.integration.GLOBAL, multi.integration.THREAD - end - } -end -function multi:canSystemThread() - return true -end -function multi:getPlatform() - return "love2d" -end -multi.integration = {} -multi.integration.love2d = {} -multi.integration.love2d.ThreadBase = - [[ -tab={...} -__THREADID__=table.remove(tab,1) -__THREADNAME__=table.remove(tab,1) -THREAD_ID=table.remove(tab,1) -require("love.filesystem") -require("love.system") -require("love.timer") -require("love.image") -local multi = require("multi") -GLOBAL={} -isMainThread=false -setmetatable(GLOBAL,{ - __index=function(t,k) - __sync__() - return __proxy__[k] - end, - __newindex=function(t,k,v) - __sync__() - __proxy__[k]=v - if type(v)=="userdata" then - __MainChan__:push(v) - else - __MainChan__:push("SYNC "..type(v).." "..k.." "..resolveData(v)) - end - end, -}) -function __sync__() - local data=__mythread__:pop() - while data do - love.timer.sleep(.01) - if type(data)=="string" then - local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") - if name=="__DIEPLZ"..__THREADID__.."__" then - error("Thread: "..__THREADID__.." has been stopped!") - end - if cmd=="SYNC" then - __proxy__[name]=resolveType(tp,d) - end - else - __proxy__[name]=data - end - data=__mythread__:pop() - end -end -function ToStr(val, name, skipnewlines, depth) - skipnewlines = skipnewlines or false - depth = depth or 0 - local tmp = string.rep(" ", depth) - if name then - if type(name) == "string" then - tmp = tmp .. "[\""..name.."\"] = " - else - tmp = tmp .. "["..(name or "").."] = " - end - end - if type(val) == "table" then - tmp = tmp .. "{" .. (not skipnewlines and " " or "") - for k, v in pairs(val) do - tmp = tmp .. ToStr(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and " " or "") - end - tmp = tmp .. string.rep(" ", depth) .. "}" - elseif type(val) == "number" then - tmp = tmp .. tostring(val) - elseif type(val) == "string" then - tmp = tmp .. string.format("%q", val) - elseif type(val) == "boolean" then - tmp = tmp .. (val and "true" or "false") - elseif type(val) == "function" then - tmp = tmp .. "loadDump([===["..dump(val).."]===])" - else - tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\"" - end - return tmp -end -function resolveType(tp,d) - if tp=="number" then - return tonumber(d) - elseif tp=="bool" then - return (d=="true") - elseif tp=="function" then - return loadDump("[==["..d.."]==]") - elseif tp=="table" then - return loadstring("return "..d)() - elseif tp=="nil" then - return nil - else - return d - end -end -function resolveData(v) - local data="" - if type(v)=="table" then - return ToStr(v) - elseif type(v)=="function" then - return dump(v) - elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then - return tostring(v) - end - return data -end -sThread={} -local function randomString(n) - local c=os.clock() - local a=0 - while os.clock()" - c.Id = count - c.creationTime = os.clock() - count = count + 1 - c.thread = love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE", dump(func))) - livingThreads[count] = {true, name} - livingThreads[c.thread] = c - c.OnError = multi:newConnection() - c.thread:start(c.ID, c.name, THREAD_ID, ...) - function c:kill() - multi.integration.GLOBAL["__DIEPLZ" .. self.ID .. "__"] = "__DIEPLZ" .. self.ID .. "__" - end - return c -end -function love.threaderror(thread, errorstr) - multi.OnError:Fire(thread, errorstr) - livingThreads[thread].OnError:Fire( - threads[i], - err, - "Error in systemThread: '" .. livingThreads[thread].name .. "' <" .. errorstr .. ">" - ) - multi.print("Error in systemThread: " .. tostring(thread) .. ": " .. errorstr) -end -local THREAD = {} -function THREAD.set(name, val) - GLOBAL[name] = val -end -function THREAD.get(name) - return GLOBAL[name] -end -function THREAD.waitFor(name) - repeat - multi:uManager() - until GLOBAL[name] - return GLOBAL[name] -end -function THREAD.getCores() - return love.system.getProcessorCount() -end -function THREAD.sleep(n) - love.timer.sleep(n) -end -function THREAD.hold(n) - repeat - multi:uManager() - until n() -end -__channels__ = {} -multi.integration.GLOBAL = GLOBAL -multi.integration.THREAD = THREAD -updater = - multi:newLoop( - function(self) - local data = multi.integration.love2d.mainChannel:pop() - while data do - if type(data) == "string" then - local cmd, tp, name, d = data:match("(%S-) (%S-) (%S-) (.+)") - if cmd == "SYNC" then - __proxy__[name] = resolveType(tp, d) - for i = 1, #__channels__ do - -- send data to other threads - if type(v) == "userdata" then - __channels__[i]:push(v) - else - __channels__[i]:push("SYNC " .. tp .. " " .. name .. " " .. d) - end - end - elseif cmd == "NEWTHREAD" then - __channels__[#__channels__ + 1] = love.thread.getChannel(tp) - for k, v in pairs(__proxy__) do -- sync the global with each new thread - if type(v) == "userdata" then - __channels__[#__channels__]:push(v) - else - __channels__[#__channels__]:push("SYNC " .. type(v) .. " " .. k .. " " .. resolveData(v)) - end - end - end - else - __proxy__[name] = data - end - data = multi.integration.love2d.mainChannel:pop() - end - end -) -multi.OnSystemThreadDied = multi:newConnection() -local started = false -function multi.InitSystemThreadErrorHandler() - if started == true then - return - end - started = true - multi:newThread( - "ThreadErrorHandler", - function() - local threads = multi.SystemThreads - while true do - thread.sleep(.5) -- switching states often takes a huge hit on performance. half a second to tell me there is an error is good enough. - for i = #threads, 1, -1 do - local v, err, t = threads[i].thread:join(.001) - if err then - if err:find("Thread was killed!") then - livingThreads[threads[i].Id] = {false, threads[i].Name} - multi.OnSystemThreadDied:Fire(threads[i].Id) - GLOBAL["__THREADS__"] = livingThreads - table.remove(threads, i) - else - threads[i].OnError:Fire(threads[i], err, "Error in systemThread: '" .. threads[i].name .. "' <" .. err .. ">") - livingThreads[threads[i].Id] = {false, threads[i].Name} - multi.OnSystemThreadDied:Fire(threads[i].Id) - GLOBAL["__THREADS__"] = livingThreads - table.remove(threads, i) - end - end - end - end - end - ) -end -require("multi.integration.shared") -multi.print("Integrated Love2d!") -return { - init = function(t) - if t then - if t.threadNamespace then - multi.integration.THREADNAME = t.threadNamespace - multi.integration.love2d.ThreadBase:gsub("sThread", t.threadNamespace) - end - if t.globalNamespace then - multi.integration.GLOBALNAME = t.globalNamespace - multi.integration.love2d.ThreadBase:gsub("GLOBAL", t.globalNamespace) - end - end - return GLOBAL, THREAD - end -} diff --git a/multi/integration/loveManager/init.lua b/multi/integration/loveManager/init.lua index 2ce9635..343a9e3 100644 --- a/multi/integration/loveManager/init.lua +++ b/multi/integration/loveManager/init.lua @@ -1,6 +1,20 @@ if ISTHREAD then error("You cannot require the loveManager from within a thread!") end +local ThreadFileData = [[ +ISTHREAD = true +THREAD = require("multi.integration.loveManager.threads") -- order is important! +scratchpad = require("multi.integration.loveManager.scratchpad") +STATUS = require("multi.integration.loveManager.status") +__IMPORTS = {...} +__FUNC__=table.remove(__IMPORTS,1) +__THREADID__=table.remove(__IMPORTS,1) +__THREADNAME__=table.remove(__IMPORTS,1) +pad=table.remove(__IMPORTS,1) +globalhpad=table.remove(__IMPORTS,1) +GLOBAL = THREAD.getGlobal() +multi, thread = require("multi").init() +THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))]] local multi, thread = require("multi.compat.love2d"):init() local THREAD = {} __THREADID__ = 0 @@ -20,7 +34,7 @@ function multi:newSystemThread(name,func,...) c.scratchpad = love.data.newByteData(string.rep("\0",multi.integration.love2d.defaultScratchpadSize)) c.name = name c.ID=THREAD_ID - c.thread=love.thread.newThread("multi/integration/loveManager/threadREF.lua") + c.thread=love.thread.newThread(ThreadFileData) c.thread:start(THREAD.dump(func),c.ID,c.name,c.scratchpad,multi.integration.love2d.GlobalScratchpad,...) GLOBAL["__THREAD_"..c.ID] = {ID=c.ID,Name=c.name,Thread=c.thread} GLOBAL["__THREAD_COUNT"] = THREAD_ID diff --git a/multi/integration/loveManager/threadREF.lua b/multi/integration/loveManager/threadREF.lua deleted file mode 100644 index c8d8956..0000000 --- a/multi/integration/loveManager/threadREF.lua +++ /dev/null @@ -1,13 +0,0 @@ -ISTHREAD = true -THREAD = require("multi.integration.loveManager.threads") -- order is important! -scratchpad = require("multi.integration.loveManager.scratchpad") -STATUS = require("multi.integration.loveManager.status") -__IMPORTS = {...} -__FUNC__=table.remove(__IMPORTS,1) -__THREADID__=table.remove(__IMPORTS,1) -__THREADNAME__=table.remove(__IMPORTS,1) -pad=table.remove(__IMPORTS,1) -globalhpad=table.remove(__IMPORTS,1) -GLOBAL = THREAD.getGlobal() -multi, thread = require("multi").init() -THREAD.loadDump(__FUNC__)(unpack(__IMPORTS)) \ No newline at end of file diff --git a/multi/integration/loveManager/threads.lua b/multi/integration/loveManager/threads.lua index f0d945e..d091e02 100644 --- a/multi/integration/loveManager/threads.lua +++ b/multi/integration/loveManager/threads.lua @@ -150,7 +150,6 @@ function threads.getConsole() return c end if not ISTHREAD then - print("mainthread") local clock = os.clock local lastproc = clock() local queue = love.thread.getChannel("__CONSOLE__") @@ -163,7 +162,7 @@ if not ISTHREAD then print(unpack(dat)) end if clock()-lastproc>2 then - thread.sleep(.1) -- Printing is for humans, sleep can be big to lower processing + thread.sleep(.1) end end end) diff --git a/multi/integration/shared.lua b/multi/integration/shared.lua index 6562ea3..7521250 100644 --- a/multi/integration/shared.lua +++ b/multi/integration/shared.lua @@ -21,27 +21,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local multi, thread = require("multi").init() -function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends - local c = {} -- where we will store our object - c.name = name -- set the name this is important for the love2d side - c.linda = lanes.linda() -- lanes is a bit easier, create the linda on the main thread - function c:push(v) -- push to the queue - self.linda:send("Q", v) - end - function c:pop() -- pop the queue - return ({self.linda:receive(0, "Q")})[2] - end - function c:peek() - return self.linda:get("Q") - end - function c:init() -- mimic the feature that love2d requires, so code can be consistent - return self - end - multi.integration.GLOBAL[name] = c -- send the object to the thread through the global interface - return c -end - function multi:newSystemThreadedConnection(name, protect) local c = {} c.name = name or error("You must provide a name for the connection object!")