diff --git a/init.lua b/init.lua index 5392cda..eebca03 100644 --- a/init.lua +++ b/init.lua @@ -68,38 +68,24 @@ setmetatable(multi.DestroyedObj, { }) multi.DESTROYED = multi.DestroyedObj -multi.ROOTPROCESS = "rootprocess" -multi.CONNECTOR = "connector" -- To be deprecated -multi.CONNECTION = "connector" -- To be changed to connection and replace connector (v17.x,x) -multi.TIMEMASTER = "timemaster" -multi.PROCESS = "process" -multi.TIMER = "timer" -multi.EVENT = "event" -multi.UPDATER = "updater" -multi.ALARM = "alarm" -multi.LOOP = "loop" -multi.TLOOP = "tloop" -multi.STEP = "step" -multi.TSTEP = "tstep" -multi.THREAD = "thread" -multi.SERVICE = "service" -multi.THREADEDFUNCTION = "threaded_function" -- To be deprecated -multi.FUNCTION = "threaded_function" -- To be changed to connection and replace connector (v17.x,x) - --- Extensions -multi.PROXY = "proxy" -multi.STHREAD = "s_thread" -multi.SQUEUE = "s_queue" -multi.STABLE = "s_table" -multi.SJOBQUEUE = "s_jobqueue" -multi.SCONNECTION = "s_connection" -multi.SPROCESS = "s_process" -multi.SFUNCTION = "s_function" +-- I don't like modifying the global namespace, so I prepend a "$" if not _G["$multi"] then _G["$multi"] = {multi = multi, thread = thread} end +local types = {} +function multi.registerType(typ, p) + if multi[typ:upper():gsub("_","")] then return typ end + multi[typ:upper():gsub("_","")] = typ + table.insert(types, {typ, p or typ}) + return typ +end + +function multi.getTypes() + return types +end + multi.Version = "16.0.0" multi.Name = "root" multi.NIL = {Type="NIL"} @@ -107,7 +93,7 @@ local NIL = multi.NIL multi.Mainloop = {} multi.Children = {} multi.Active = true -multi.Type = multi.ROOTPROCESS +multi.Type = multi.registerType("rootprocess") multi.LinkedPath = multi multi.TIMEOUT = "TIMEOUT" multi.TID = 0 @@ -317,7 +303,7 @@ function multi:newConnection(protect,func,kill) return cn end}) - c.Type=multi.CONNECTION + c.Type=multi.registerType("connector", "connections") c.func={} c.ID=0 local protect=protect or false @@ -483,7 +469,8 @@ function multi:newConnection(protect,func,kill) end function c:Hold() - return multi.hold(self) + local rets = {multi.hold(self)} + return unpack(rets) end c.connect=c.Connect @@ -538,7 +525,7 @@ end function multi:SetTime(n) if not n then n=3 end local c=self:newBase() - c.Type=multi.TIMEMASTER + c.Type=multi.registerType("timemaster") c.timer=self:newTimer() c.timer:Start() c.set=n @@ -567,7 +554,7 @@ end -- Timer stuff done multi.PausedObjects = {} function multi:Pause() - if self.Type==multi.ROOTPROCESS then + if self.Type==multi.registerType("rootprocess") then multi.print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") else self.Active=false @@ -578,7 +565,7 @@ function multi:Pause() end function multi:Resume() - if self.Type==multi.PROCESS or self.Type==multi.ROOTPROCESS then + if self.Type==multi.registerType("process", "processes") or self.Type==multi.registerType("rootprocess") then self.Active=true local c=self:getChildren() for i=1,#c do @@ -594,7 +581,7 @@ function multi:Resume() end function multi:Destroy() - if self.Type==multi.PROCESS or self.Type==multi.ROOTPROCESS then + if self.Type==multi.registerType("process", "processes") or self.Type==multi.registerType("rootprocess") then local c=self:getChildren() for i=1,#c do self.OnObjectDestroyed:Fire(c[i]) @@ -648,9 +635,9 @@ end --Constructors [CORE] local _tid = 0 function multi:newBase(ins) - if not(self.Type==multi.ROOTPROCESS or self.Type==multi.PROCESS) then multi.error('Can only create an object on multi or an interface obj') return false end + if not(self.Type==multi.registerType("rootprocess") or self.Type==multi.registerType("process", "processes")) then multi.error('Can only create an object on multi or an interface obj') return false end local c = {} - if self.Type==multi.PROCESS then + if self.Type==multi.registerType("process", "processes") then setmetatable(c, {__index = multi}) else setmetatable(c, {__index = multi}) @@ -687,7 +674,7 @@ end function multi:newTimer() local c={} - c.Type=multi.TIMER + c.Type=multi.registerType("timer", "timers") local time=0 local count=0 local paused=false @@ -720,7 +707,7 @@ end --Core Actors function multi:newEvent(task, func) local c=self:newBase() - c.Type=multi.EVENT + c.Type=multi.registerType("event", "events") local task = task or function() end function c:Act() local t = task(self) @@ -747,7 +734,7 @@ end function multi:newUpdater(skip, func) local c=self:newBase() - c.Type=multi.UPDATER + c.Type=multi.registerType("updater", "updaters") local pos = 1 local skip = skip or 1 function c:Act() @@ -773,7 +760,7 @@ end function multi:newAlarm(set, func) local c=self:newBase() - c.Type=multi.ALARM + c.Type=multi.registerType("alarm", "alarms") c:setPriority("Low") c.set=set or 0 local count = 0 @@ -814,7 +801,7 @@ end function multi:newLoop(func, notime) local c=self:newBase() - c.Type=multi.LOOP + c.Type = multi.registerType("loop", "loops") local start=clock() if notime then function c:Act() @@ -842,7 +829,7 @@ end function multi:newStep(start,reset,count,skip) local c=self:newBase() think=1 - c.Type=multi.STEP + c.Type=multi.registerType("step", "steps") c.pos=start or 1 c.endAt=reset or math.huge c.skip=skip or 0 @@ -901,7 +888,7 @@ end function multi:newTLoop(func, set) local c=self:newBase() - c.Type=multi.TLOOP + c.Type=multi.registerType("tloop", "tloops") c.set=set or 0 c.timer=self:newTimer() c.life=0 @@ -951,7 +938,7 @@ end function multi:newTStep(start,reset,count,set) local c=self:newStep(start,reset,count) - c.Type=multi.TSTEP + c.Type=multi.registerType("tstep", "tsteps") c:setPriority("Low") local reset = reset or math.huge c.timer=clock() @@ -1068,7 +1055,7 @@ function multi:newProcessor(name, nothread, priority) local name = name or "Processor_" .. sandcount sandcount = sandcount + 1 c.Mainloop = {} - c.Type = multi.PROCESS + c.Type = multi.registerType("process", "processes") local Active = nothread or false c.Name = name or "" c.threads = {} @@ -1279,7 +1266,7 @@ function thread.hold(n, opt) if type(n) == "number" then thread.getRunningThread().lastSleep = clock() return yield(CMD, t_sleep, n or 0, nil, interval) - elseif type(n) == "table" and n.Type == multi.CONNECTION then + elseif type(n) == "table" and n.Type == multi.registerType("connector", "connections") then return yield(CMD, t_hold, conn_test(n), nil, interval) elseif type(n) == "table" and n.Hold ~= nil then return n:Hold(opt) @@ -1442,7 +1429,7 @@ function thread:newFunctionBase(generator, holdme, TYPE) return temp end setmetatable(tfunc, tfunc) - tfunc.Type = TYPE or multi.FUNCTION + tfunc.Type = TYPE or multi.registerType("function", "functions") return tfunc end end @@ -1543,14 +1530,14 @@ function thread:newThread(name, func, ...) c.Name=name c.thread=create(func) c.sleep=1 - c.Type = multi.THREAD + c.Type = multi.registerType("thread", "threads") c.TID = threadid c.firstRunDone=false c._isPaused = false c.returns = {} c.isError = false - if self.Type == multi.PROCESS then + if self.Type == multi.registerType("process", "processes") then c.OnError = self:newConnection(true,nil,true) c.OnDeath = self:newConnection(true,nil,true) else @@ -1611,13 +1598,13 @@ function thread:newThread(name, func, ...) c.Destroy = c.Kill if thread.isThread() then - if self.Type == multi.PROCESS then + if self.Type == multi.registerType("process", "processes") then table.insert(self.startme, c) else table.insert(threadManager.startme, c) end else - if self.Type == multi.PROCESS then + if self.Type == multi.registerType("process", "processes") then table.insert(self.startme, c) else table.insert(threadManager.startme, c) @@ -1626,7 +1613,7 @@ function thread:newThread(name, func, ...) globalThreads[c] = multi threadid = threadid + 1 - if self.Type == multi.PROCESS then + if self.Type == multi.registerType("process", "processes") then self:create(c) else threadManager:create(c) @@ -1859,7 +1846,7 @@ end function multi:newService(func) -- Priority managed threads local c = {} - c.Type = multi.SERVICE + c.Type = multi.registerType("service", "services") c.OnStopped = self:newConnection() c.OnStarted = self:newConnection() local Service_Data = {} @@ -2034,7 +2021,7 @@ local function doOpt() if type(n) == "number" then thread.getRunningThread().lastSleep = clock() return yield(CMD, t_sleep, n or 0, nil, interval) - elseif type(n) == "table" and n.Type == multi.CONNECTION then + elseif type(n) == "table" and n.Type == multi.registerType("connector", "connections") then local rdy = function() return false end @@ -2071,22 +2058,32 @@ local function doOpt() end local init = false +multi.settingsHook = multi:newConnection() function multi.init(settings, realsettings) if settings == multi then settings = realsettings end if init then return _G["$multi"].multi,_G["$multi"].thread end init = true if type(settings)=="table" then + multi.defaultSettings = settings + if settings.priority then multi.mainloop = multi.p_mainloop else multi.mainloop = multi.mainloopRef end + if settings.findopt then find_optimization = true doOpt() multi.enableOptimization:Fire(multi, thread) end + + if settings.debugging then + require("multi.integration.debugManager") + end + + multi.settingsHook:Fire(settings) end return _G["$multi"].multi,_G["$multi"].thread end @@ -2194,7 +2191,7 @@ function multi:getLoad() end function multi:setPriority(s) - if not self.IsAnActor or self.Type == multi.PROCESS then return end + if not self.IsAnActor or self.Type == multi.registerType("process", "processes") then return end if type(s)=="number" then self.Priority=s elseif type(s)=='string' then diff --git a/integration/debugManager/init.lua b/integration/debugManager/init.lua index eae78be..d397d37 100644 --- a/integration/debugManager/init.lua +++ b/integration/debugManager/init.lua @@ -1,5 +1,7 @@ local multi, thread = require("multi"):init() +multi.defaultSettings.debugging = true + local dbg = {} local creation_hook @@ -11,6 +13,8 @@ creation_hook = function(obj, process) end end +local debug_stats = {} + local tmulti = multi:getThreadManagerProcess() multi.OnObjectCreated(creation_hook) tmulti.OnObjectCreated(creation_hook) @@ -32,6 +36,4 @@ tmulti.OnObjectCreated(creation_hook) multi.SERVICE = "service" multi.PROXY = "proxy" multi.THREADEDFUNCTION = "threaded_function" -]] - -return dbg \ No newline at end of file +]] \ No newline at end of file diff --git a/integration/lanesManager/extensions.lua b/integration/lanesManager/extensions.lua index 37526c7..4ff3605 100644 --- a/integration/lanesManager/extensions.lua +++ b/integration/lanesManager/extensions.lua @@ -34,7 +34,7 @@ function multi:newSystemThreadedQueue(name) local c = {} c.Name = name c.linda = lanes.linda() - c.Type = multi.SQUEUE + c.Type = multi.registerType("s_queue") function c:push(v) self.linda:send("Q", v) @@ -81,7 +81,7 @@ function multi:newSystemThreadedTable(name) local c = {} c.link = lanes.linda() c.Name = name - c.Type = multi.STABLE + c.Type = multi.registerType("s_table") function c:init() return self @@ -121,7 +121,7 @@ end function multi:newSystemThreadedJobQueue(n) local c = {} c.cores = n or THREAD.getCores()*2 - c.Type = multi.SJOBQUEUE + c.Type = multi.registerType("s_jobqueue") c.OnJobCompleted = multi:newConnection() local funcs = multi:newSystemThreadedTable() local queueJob = multi:newSystemThreadedQueue() @@ -250,7 +250,7 @@ end function multi:newSystemThreadedConnection(name) local name = name or multi.randomString(16) local c = {} - c.Type = multi.SCONNECTION + c.Type = multi.registerType("s_connection") c.CONN = 0x00 c.TRIG = 0x01 c.PING = 0x02 diff --git a/integration/lanesManager/init.lua b/integration/lanesManager/init.lua index dbf7eb3..2f3e646 100644 --- a/integration/lanesManager/init.lua +++ b/integration/lanesManager/init.lua @@ -61,7 +61,7 @@ local livingThreads = {} function THREAD:newFunction(func, holdme) return thread:newFunctionBase(function(...) return multi:newSystemThread("TempSystemThread",func,...) - end, holdme, multi.SFUNCTION)() + end, holdme, multi.registerType("s_function"))() end function multi:newSystemThread(name, func, ...) @@ -75,7 +75,7 @@ function multi:newSystemThread(name, func, ...) c.loadString = {"base","package","os","io","math","table","string","coroutine"} livingThreads[count] = {true, name} c.returns = return_linda - c.Type = multi.STHREAD + c.Type = multi.registerType("s_thread") c.creationTime = os.clock() c.alive = true c.priority = THREAD.Priority_Normal diff --git a/integration/loveManager/extensions.lua b/integration/loveManager/extensions.lua index 358cf6e..f1a7f27 100644 --- a/integration/loveManager/extensions.lua +++ b/integration/loveManager/extensions.lua @@ -10,7 +10,7 @@ function multi:newSystemThreadedQueue(name) local c = {} c.Name = name - c.Type = multi.SQUEUE + c.Type = multi.registerType("s_queue") c.chan = love.thread.newChannel() function c:push(dat) @@ -54,7 +54,7 @@ function multi:newSystemThreadedTable(name) local c = {} c.Name = name - c.Type = multi.STABLE + c.Type = multi.registerType("s_table") c.tab = THREAD.createTable(name) function c:init() @@ -104,7 +104,7 @@ function multi:newSystemThreadedJobQueue(n) c.cores = n or THREAD.getCores() c.registerQueue = {} - c.Type = multi.SJOBQUEUE + c.Type = multi.registerType("s_jobqueue") c.funcs = THREAD.createTable("__JobQueue_"..jqc.."_table") c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue") c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn") diff --git a/integration/loveManager/init.lua b/integration/loveManager/init.lua index 6a26e8d..92cba27 100644 --- a/integration/loveManager/init.lua +++ b/integration/loveManager/init.lua @@ -33,6 +33,9 @@ _G.THREAD_ID = 0 local multi, thread = require("multi"):init() local GLOBAL, THREAD = require("multi.integration.loveManager.threads"):init() +multi.registerType("s_function") +multi.registerType("s_thread") + multi.integration = {} multi.isMainThread = true local threads = {} diff --git a/integration/priorityManager/init.lua b/integration/priorityManager/init.lua index 95ed193..f3fe45c 100644 --- a/integration/priorityManager/init.lua +++ b/integration/priorityManager/init.lua @@ -102,7 +102,7 @@ priorityManager.uManager = function(self) end local function processHook(obj, proc) - if obj.Type == multi.PROCESS or not(obj.IsAnActor) then return end + if obj.Type == multi.registerType("process", "processes") or not(obj.IsAnActor) then return end obj.__restoreProc = proc obj.__profiling = {} obj:reallocate(priorityManager) @@ -171,7 +171,7 @@ local function init() function multi:setPriorityScheme(scheme) - if not self.Type == multi.PROCESS or not self.Type == multi.ROOTPROCESS then + if not self.Type == multi.registerType("process", "processes") or not self.Type == multi.registerType("rootprocess") then multi.warn("You should only invoke setPriorityScheme on a processor object!") end diff --git a/integration/pseudoManager/extensions.lua b/integration/pseudoManager/extensions.lua index 03550b6..5e6a8a2 100644 --- a/integration/pseudoManager/extensions.lua +++ b/integration/pseudoManager/extensions.lua @@ -35,6 +35,7 @@ end function multi:newSystemThreadedQueue(name) local c = {} + c.Type = multi.registerType("s_queue") function c:push(v) table.insert(self,v) end @@ -64,6 +65,7 @@ end function multi:newSystemThreadedTable(name) local c = {} + c.Type = multi.registerType("s_table") function c:init() return self end @@ -88,7 +90,7 @@ function multi:newSystemThreadedJobQueue(n) c.cores = n or THREAD.getCores() c.registerQueue = {} - c.Type = multi.SJOBQUEUE + c.Type = multi.registerType("s_jobqueue") c.funcs = multi:newSystemThreadedTable("__JobQueue_"..jqc.."_table") c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue") c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn") diff --git a/integration/pseudoManager/init.lua b/integration/pseudoManager/init.lua index 91e0824..ec2f70e 100644 --- a/integration/pseudoManager/init.lua +++ b/integration/pseudoManager/init.lua @@ -91,6 +91,7 @@ function multi:newSystemThread(name, func, ...) local GLOBAL, THREAD = activator.init(thread, env) local th = thread:newISOThread(name, func, env, ...) + th.Type = multi.registerType("s_thread", "pseudoThreads") id = id + 1 @@ -104,7 +105,7 @@ THREAD.newSystemThread = multi.newSystemThread function THREAD:newFunction(func,holdme) return thread:newFunctionBase(function(...) return multi:newSystemThread("TempSystemThread",func,...) - end,holdme)() + end, holdme, multi.registerType("s_function", "pseudoFunctions"))() end multi.print("Integrated Pesudo Threading!") diff --git a/integration/sharedExtensions/init.lua b/integration/sharedExtensions/init.lua index c916b0f..7d4af48 100644 --- a/integration/sharedExtensions/init.lua +++ b/integration/sharedExtensions/init.lua @@ -35,9 +35,9 @@ function multi:chop(obj) local list = {[0] = multi.randomString(12)} _G[list[0]] = obj for i,v in pairs(obj) do - if type(v) == "function" or type(v) == "table" and v.Type == multi.THREADEDFUNCTION then + if type(v) == "function" or type(v) == "table" and v.Type == multi.registerType("s_function") then table.insert(list, i) - elseif type(v) == "table" and v.Type == multi.CONNECTOR then + elseif type(v) == "table" and v.Type == multi.registerType("connector", "connections") then table.insert(list, {i, multi:newProxy(multi:chop(v)):init()}) end end @@ -79,7 +79,7 @@ function multi:newProxy(list) self.recv = multi:newSystemThreadedQueue(self.name.."_R"):init() self.funcs = list self._funcs = copy(list) - self.Type = multi.PROXY + self.Type = multi.registerType("proxy", "proxies") self.TID = THREAD_ID thread:newThread("Proxy_Handler_" .. multi.randomString(4), function() @@ -99,7 +99,7 @@ function multi:newProxy(list) end for i = 1,#ret do - if type(ret[i]) == "table" and ret[i].Type ~= nil and ret[i].Type ~= multi.PROXY then + if type(ret[i]) == "table" and ret[i].Type ~= nil and ret[i].Type ~= multi.registerType("proxy", "proxies") then ret[i] = "\1PARENT_REF" end if type(ret[i]) == "table" and getmetatable(ret[i]) then @@ -133,7 +133,7 @@ function multi:newProxy(list) end self.send = THREAD.waitFor(self.name.."_S"):init() self.recv = THREAD.waitFor(self.name.."_R"):init() - self.Type = multi.PROXY + self.Type = multi.registerType("proxy", "proxies") for _,v in pairs(funcs) do if type(v) == "table" then -- We have a connection @@ -184,11 +184,14 @@ function multi:newProxy(list) cp.funcs = copy(self._funcs) cp.init = function(self) local multi, thread = require("multi"):init() - if multi.integration then - GLOBAL = multi.integration.GLOBAL - THREAD = multi.integration.THREAD - end + -- if multi.integration then + -- GLOBAL = multi.integration.GLOBAL + -- THREAD = multi.integration.THREAD + -- end local proxy = THREAD.waitFor(self.proxy_link) + for i,v in pairs(proxy) do + print("proxy",i,v) + end proxy.funcs = self.funcs return proxy:init() end @@ -211,7 +214,7 @@ function multi:newSystemThreadedProcessor(cores) setmetatable(c,{__index = multi}) - c.Type = multi.SPROCESS + c.Type = multi.registerType("s_process", "s_processes") c.threads = {} c.cores = cores or 8 c.Name = name @@ -331,3 +334,4 @@ function multi:newSystemThreadedProcessor(cores) return c end + diff --git a/tests/threadtests.lua b/tests/threadtests.lua index d2bb646..dcf3a8b 100644 --- a/tests/threadtests.lua +++ b/tests/threadtests.lua @@ -102,7 +102,7 @@ multi:newThread("Scheduler Thread",function() t, val = thread.hold(function() return worked - end,{sleep=1}) + end,{sleep=2}) if val == multi.TIMEOUT then multi.error("SystemThreadedTables: Failed") @@ -190,9 +190,11 @@ multi:newThread("Scheduler Thread",function() thread.sleep(1) os.exit(1) end) - local stp = multi:newSystemThreadedProcessor(1) + local stp = multi:newSystemThreadedProcessor(5) - local tloop = stp:newTLoop(nil, 1) + local tloop = stp:newTLoop(function() + print("Test") + end, 1) multi:newSystemThread("Testing proxy copy THREAD",function(tloop) local multi, thread = require("multi"):init() @@ -235,18 +237,18 @@ multi:newThread("Scheduler Thread",function() end) t, val = thread.hold(function() - return count == 10 + return proxy_test end,{sleep=5}) if val == multi.TIMEOUT then multi.error("SystemThreadedProcessor/Proxies: Failed") os.exit(1) + else + multi.success("SystemThreadedProcessor: OK") end thread.sleep(2) - multi.success("SystemThreadedProcessor: OK") - we_good = true multi:Stop() -- Needed in love2d tests to stop the main runner end).OnError(multi.error)