Working on 16.0.0 #53

Merged
rayaman merged 120 commits from v16.0.0 into master 2024-02-25 00:00:51 -05:00
7 changed files with 93 additions and 18 deletions
Showing only changes of commit 257ed03728 - Show all commits

View File

@ -138,7 +138,7 @@ Added
alarm = stp:newAlarm(3) alarm = stp:newAlarm(3)
alarm.OnRing:Connect(function(alarm) alarm._OnRing:Connect(function(alarm)
print("Hmm...", THREAD_NAME) print("Hmm...", THREAD_NAME)
end) end)
``` ```
@ -148,9 +148,70 @@ Added
``` ```
Internally the SystemThreadedProcessor uses a JobQueue to handle things. The proxy function allows you to interact with these objects as if they were on the main thread, though there actions are carried out on the main thread. Internally the SystemThreadedProcessor uses a JobQueue to handle things. The proxy function allows you to interact with these objects as if they were on the main thread, though there actions are carried out on the main thread.
There are currently limitations to proxies. Connection proxy do not receive events on the non thread side. So connection metamethods do not work! thread.hold(proxy.conn) does work! The backend to get this to work was annoying :P Connection proxies break the rules a bit. Normally methods should always work on the thread side, however for connections in order to have actions work on the thread side you would call the connection using `obj._connName` instead of calling `obj.connName`. This allows you to have more control over connection events. See example below:
```lua
package.path = "?/init.lua;?.lua;"..package.path
This event is subscribed to on the proxy threads side of things! multi, thread = require("multi"):init({print=true})
THREAD, GLOBAL = require("multi.integration.lanesManager"):init()
stp = multi:newSystemThreadedProcessor(8)
alarm = stp:newAlarm(3)
-- This doesn't work since this event has already been subscribed to internally on the thread to get thread.hold(alarm.OnRing) to work. But as many events to alarm.OnRing can be made!
thread:newThread(function()
print("Hold on proxied connection", thread.hold(alarm._OnRing))
end)
alarm.OnRing(function(a)
print("OnRing",a, THREAD_NAME, THREAD_ID)
end)
print("alarm.OnRing", alarm.OnRing.Type)
print("alarm._OnRing", alarm._OnRing.Type)
thread:newThread(function()
print("Hold on proxied no proxy connection", thread.hold(alarm.OnRing))
end)
thread:newThread(function()
print("Hold on proxied no proxy connection", thread.hold(alarm.OnRing))
end)
-- This doesn't work since this event has already been subscribed to internally on the thread to get thread.hold(alarm.OnRing) to work. But as many events to alarm.OnRing can be made!
thread:newThread(function()
print("Hold on proxied connection", thread.hold(alarm._OnRing))
end)
alarm._OnRing(function(a)
print("_OnRing",a, THREAD_NAME, THREAD_ID)
a:Reset(1)
end)
multi:mainloop()
```
Output:
```
INFO: Integrated Lanes Threading!
alarm.OnRing connector
alarm._OnRing proxy
_OnRing table: 025EB128 STJQ_cjKsEZHg 1 <-- This can change each time you run this example!
OnRing table: 018BC0C0 MAIN_THREAD 0
Hold on proxied no proxy connection table: 018BC0C0 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
Hold on proxied no proxy connection table: 018BC0C0 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
_OnRing table: 025EB128 STJQ_cjKsEZHg 1
OnRing table: 018BC0C0 MAIN_THREAD 0
_OnRing table: 025EB128 STJQ_cjKsEZHg 1
OnRing table: 018BC0C0 MAIN_THREAD 0
... (Will repeat ever second now)
_OnRing table: 025EB128 STJQ_cjKsEZHg 1
OnRing table: 018BC0C0 MAIN_THREAD 0
```
The proxy version can only subscribe to events on the proxy thread, which means that connection metamethods will not work with the proxy version (`_OnRing` on the non proxy thread side), but the (`OnRing`) version will work. Cleverly handling the proxy thread and the non proxy thread will allow powerful connection logic. Also this is not a full system threaded connection. **Proxies should only be used between 2 threads!** To keep things fast I'm using simple queues to transfer data. There is no guarantee that things will work!
Currently supporting: Currently supporting:
- proxyLoop = STP:newLoop(...) - proxyLoop = STP:newLoop(...)

View File

@ -80,6 +80,7 @@ multi.STEP = "step"
multi.TSTEP = "tstep" multi.TSTEP = "tstep"
multi.THREAD = "thread" multi.THREAD = "thread"
multi.SERVICE = "service" multi.SERVICE = "service"
multi.PROXY = "proxy"
if not _G["$multi"] then if not _G["$multi"] then
_G["$multi"] = {multi = multi, thread = thread} _G["$multi"] = {multi = multi, thread = thread}

View File

@ -36,6 +36,9 @@ lanes = require("lanes").configure()
multi.SystemThreads = {} multi.SystemThreads = {}
multi.isMainThread = true multi.isMainThread = true
_G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0
function multi:canSystemThread() function multi:canSystemThread()
return true return true
end end

View File

@ -32,15 +32,13 @@ THREAD = require("multi.integration.loveManager.threads")
sThread = THREAD sThread = THREAD
__IMPORTS = {...} __IMPORTS = {...}
__FUNC__=table.remove(__IMPORTS,1) __FUNC__=table.remove(__IMPORTS,1)
__THREADID__=table.remove(__IMPORTS,1) THREAD_ID=table.remove(__IMPORTS,1)
__THREADNAME__=table.remove(__IMPORTS,1) THREAD_NAME=table.remove(__IMPORTS,1)
THREAD_NAME = __THREADNAME__ math.randomseed(THREAD_ID)
THREAD_ID = __THREADID__
math.randomseed(__THREADID__)
math.random() math.random()
math.random() math.random()
math.random() math.random()
stab = THREAD.createStaticTable(__THREADNAME__ .. __THREADID__) stab = THREAD.createStaticTable(THREAD_NAME .. THREAD_ID)
GLOBAL = THREAD.getGlobal() GLOBAL = THREAD.getGlobal()
if GLOBAL["__env"] then if GLOBAL["__env"] then
local env = THREAD.unpackENV(GLOBAL["__env"]) local env = THREAD.unpackENV(GLOBAL["__env"])
@ -60,15 +58,15 @@ stab["returns"] = {THREAD.loadDump(__FUNC__)(multi.unpack(__IMPORTS))}
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local THREAD = {} local THREAD = {}
__THREADID__ = 0 _G.THREAD_NAME = "MAIN_THREAD"
__THREADNAME__ = "MainThread" _G.THREAD_ID = 0
multi.integration = {} multi.integration = {}
local THREAD = require("multi.integration.loveManager.threads") local THREAD = require("multi.integration.loveManager.threads")
local GLOBAL = THREAD.getGlobal() local GLOBAL = THREAD.getGlobal()
local THREAD_ID = 1
multi.isMainThread = true multi.isMainThread = true
function multi:newSystemThread(name, func, ...) function multi:newSystemThread(name, func, ...)
THREAD_ID = THREAD_ID + 1
local c = {} local c = {}
c.name = name c.name = name
c.ID = THREAD_ID c.ID = THREAD_ID
@ -79,7 +77,7 @@ function multi:newSystemThread(name, func, ...)
c.OnError = multi:newConnection() c.OnError = multi:newConnection()
GLOBAL["__THREAD_" .. c.ID] = {ID = c.ID, Name = c.name, Thread = c.thread} GLOBAL["__THREAD_" .. c.ID] = {ID = c.ID, Name = c.name, Thread = c.thread}
GLOBAL["__THREAD_COUNT"] = THREAD_ID GLOBAL["__THREAD_COUNT"] = THREAD_ID
THREAD_ID = THREAD_ID + 1
function c:getName() return c.name end function c:getName() return c.name end
thread:newThread(name .. "_System_Thread_Handler",function() thread:newThread(name .. "_System_Thread_Handler",function()
if name == "SystemThreaded Function Handler" then if name == "SystemThreaded Function Handler" then

View File

@ -42,6 +42,8 @@ local multi, thread = require("multi.compat.lovr2d"):init()
local THREAD = {} local THREAD = {}
__THREADID__ = 0 __THREADID__ = 0
__THREADNAME__ = "MainThread" __THREADNAME__ = "MainThread"
_G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0
multi.integration={} multi.integration={}
multi.integration.lovr2d={} multi.integration.lovr2d={}
local THREAD = require("multi.integration.lovrManager.threads") local THREAD = require("multi.integration.lovrManager.threads")

View File

@ -35,6 +35,9 @@ multi.isMainThread = true
local activator = require("multi.integration.pseudoManager.threads") local activator = require("multi.integration.pseudoManager.threads")
local GLOBAL, THREAD = activator.init(thread) local GLOBAL, THREAD = activator.init(thread)
_G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0
function multi:canSystemThread() -- We are emulating system threading function multi:canSystemThread() -- We are emulating system threading
return true return true
end end

View File

@ -67,7 +67,7 @@ function multi:newProxy(list)
function c:init() function c:init()
local multi, thread = nil, nil local multi, thread = nil, nil
if THREAD_NAME then if THREAD_ID>0 then
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local function check() local function check()
return self.send:pop() return self.send:pop()
@ -113,11 +113,19 @@ function multi:newProxy(list)
self.Type = multi.PROXY self.Type = multi.PROXY
for _,v in pairs(self.funcs) do for _,v in pairs(self.funcs) do
if type(v) == "table" then if type(v) == "table" then
-- We have a connection
v[2]:init() v[2]:init()
self[v[1]] = v[2] self["_"..v[1]] = v[2]
v[2].Parent = self v[2].Parent = self
setmetatable(v[2],getmetatable(multi:newConnection()))
self[v[1]] = multi:newConnection()
thread:newThread(function()
while true do
self[v[1]]:Fire(thread.hold(alarm["_"..v[1]]))
end
end)
else else
lastObj = self
self[v] = thread:newFunction(function(self,...) self[v] = thread:newFunction(function(self,...)
if self == me then if self == me then
me.send:push({v, true, ...}) me.send:push({v, true, ...})
@ -146,8 +154,6 @@ function multi:newProxy(list)
return c return c
end end
multi.PROXY = "proxy"
local targets = {} local targets = {}
local nFunc = 0 local nFunc = 0
@ -416,6 +422,7 @@ end
-- Modify thread.hold to handle proxies -- Modify thread.hold to handle proxies
local thread_ref = thread.hold local thread_ref = thread.hold
function thread.hold(n, opt) function thread.hold(n, opt)
--if type(n) == "table" then print(n.Type, n.isConnection()) end
if type(n) == "table" and n.Type == multi.PROXY and n.isConnection() then if type(n) == "table" and n.Type == multi.PROXY and n.isConnection() then
local ready = false local ready = false
local args local args