15.3.0 system threaded connections #48

Merged
rayaman merged 18 commits from 15.3.0-SystemThreadedConnections into v15.3.0 2022-09-22 10:28:12 -04:00
10 changed files with 429 additions and 87 deletions

View File

@ -1,6 +1,6 @@
# Multi Version: 15.3.0 # Multi Version: 15.3.0 Connecting the dots
**Key Changes** **Key Changes**
- - Bug fix
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it! Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it!
@ -16,8 +16,9 @@ Progress is being made in [v15.3.0](https://github.com/rayaman/multi/tree/v15.3.
INSTALLING INSTALLING
---------- ----------
Link to optional dependencies: Link to optional dependencies:
[lanes](https://github.com/LuaLanes/lanes) - [lanes](https://github.com/LuaLanes/lanes)
[love2d](https://love2d.org/)
- [love2d](https://love2d.org/)
To install copy the multi folder into your environment and you are good to go</br> To install copy the multi folder into your environment and you are good to go</br>
If you want to use the system threads, then you'll need to install lanes or love2d game engine! If you want to use the system threads, then you'll need to install lanes or love2d game engine!

View File

@ -1,8 +1,122 @@
# Changelog # Changelog
Table of contents Table of contents
--- ---
[Update 15.2.1 - Bug fix](#update-1521---bug-fix)</br>
[Update 15.2.0 - Upgrade Complete](#update-1520---upgrade-complete)</br>[Update 15.1.0 - Hold the thread!](#update-1510---hold-the-thread)</br>[Update 15.0.0 - The art of faking it](#update-1500---the-art-of-faking-it)</br>[Update 14.2.0 - Bloatware Removed](#update-1420---bloatware-removed)</br>[Update 14.1.0 - A whole new world of possibilities](#update-1410---a-whole-new-world-of-possibilities)</br>[Update 14.0.0 - Consistency, Additions and Stability](#update-1400---consistency-additions-and-stability)</br>[Update 13.1.0 - Bug fixes and features added](#update-1310---bug-fixes-and-features-added)</br>[Update 13.0.0 - Added some documentation, and some new features too check it out!](#update-1300---added-some-documentation-and-some-new-features-too-check-it-out)</br>[Update 12.2.2 - Time for some more bug fixes!](#update-1222---time-for-some-more-bug-fixes)</br>[Update 12.2.1 - Time for some bug fixes!](#update-1221---time-for-some-bug-fixes)</br>[Update 12.2.0 - The chains of binding](#update-1220---the-chains-of-binding)</br>[Update 12.1.0 - Threads just can't hold on anymore](#update-1210---threads-just-cant-hold-on-anymore)</br>[Update: 12.0.0 - Big update (Lots of additions some changes)](#update-1200---big-update-lots-of-additions-some-changes)</br>[Update: 1.11.1 - Small Clarification on Love](#update-1111---small-clarification-on-love)</br>[Update: 1.11.0](#update-1110)</br>[Update: 1.10.0](#update-1100)</br>[Update: 1.9.2](#update-192)</br>[Update: 1.9.1 - Threads can now argue](#update-191---threads-can-now-argue)</br>[Update: 1.9.0](#update-190)</br>[Update: 1.8.7](#update-187)</br>[Update: 1.8.6](#update-186)</br>[Update: 1.8.5](#update-185)</br>[Update: 1.8.4](#update-184)</br>[Update: 1.8.3 - Mainloop recieves some needed overhauling](#update-183---mainloop-recieves-some-needed-overhauling)</br>[Update: 1.8.2](#update-182)</br>[Update: 1.8.1](#update-181)</br>[Update: 1.7.6](#update-176)</br>[Update: 1.7.5](#update-175)</br>[Update: 1.7.4](#update-174)</br>[Update: 1.7.3](#update-173)</br>[Update: 1.7.2](#update-172)</br>[Update: 1.7.1 - Bug Fixes Only](#update-171---bug-fixes-only)</br>[Update: 1.7.0 - Threading the systems](#update-170---threading-the-systems)</br>[Update: 1.6.0](#update-160)</br>[Update: 1.5.0](#update-150)</br>[Update: 1.4.1 (4/10/2017) - First Public release of the library](#update-141-4102017---first-public-release-of-the-library)</br>[Update: 1.4.0 (3/20/2017)](#update-140-3202017)</br>[Update: 1.3.0 (1/29/2017)](#update-130-1292017)</br>[Update: 1.2.0 (12.31.2016)](#update-120-12312016)</br>[Update: 1.1.0](#update-110)</br>[Update: 1.0.0](#update-100)</br>[Update: 0.6.3](#update-063)</br>[Update: 0.6.2](#update-062)</br>[Update: 0.6.1-6](#update-061-6)</br>[Update: 0.5.1-6](#update-051-6)</br>[Update: 0.4.1](#update-041)</br>[Update: 0.3.0 - The update that started it all](#update-030---the-update-that-started-it-all)</br>[Update: EventManager 2.0.0](#update-eventmanager-200)</br>[Update: EventManager 1.2.0](#update-eventmanager-120)</br>[Update: EventManager 1.1.0](#update-eventmanager-110)</br>[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)</br>[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different) [Update 15.2.0 - Upgrade Complete](#update-1520---upgrade-complete)</br>[Update 15.1.0 - Hold the thread!](#update-1510---hold-the-thread)</br>[Update 15.0.0 - The art of faking it](#update-1500---the-art-of-faking-it)</br>[Update 14.2.0 - Bloatware Removed](#update-1420---bloatware-removed)</br>[Update 14.1.0 - A whole new world of possibilities](#update-1410---a-whole-new-world-of-possibilities)</br>[Update 14.0.0 - Consistency, Additions and Stability](#update-1400---consistency-additions-and-stability)</br>[Update 13.1.0 - Bug fixes and features added](#update-1310---bug-fixes-and-features-added)</br>[Update 13.0.0 - Added some documentation, and some new features too check it out!](#update-1300---added-some-documentation-and-some-new-features-too-check-it-out)</br>[Update 12.2.2 - Time for some more bug fixes!](#update-1222---time-for-some-more-bug-fixes)</br>[Update 12.2.1 - Time for some bug fixes!](#update-1221---time-for-some-bug-fixes)</br>[Update 12.2.0 - The chains of binding](#update-1220---the-chains-of-binding)</br>[Update 12.1.0 - Threads just can't hold on anymore](#update-1210---threads-just-cant-hold-on-anymore)</br>[Update: 12.0.0 - Big update (Lots of additions some changes)](#update-1200---big-update-lots-of-additions-some-changes)</br>[Update: 1.11.1 - Small Clarification on Love](#update-1111---small-clarification-on-love)</br>[Update: 1.11.0](#update-1110)</br>[Update: 1.10.0](#update-1100)</br>[Update: 1.9.2](#update-192)</br>[Update: 1.9.1 - Threads can now argue](#update-191---threads-can-now-argue)</br>[Update: 1.9.0](#update-190)</br>[Update: 1.8.7](#update-187)</br>[Update: 1.8.6](#update-186)</br>[Update: 1.8.5](#update-185)</br>[Update: 1.8.4](#update-184)</br>[Update: 1.8.3 - Mainloop recieves some needed overhauling](#update-183---mainloop-recieves-some-needed-overhauling)</br>[Update: 1.8.2](#update-182)</br>[Update: 1.8.1](#update-181)</br>[Update: 1.7.6](#update-176)</br>[Update: 1.7.5](#update-175)</br>[Update: 1.7.4](#update-174)</br>[Update: 1.7.3](#update-173)</br>[Update: 1.7.2](#update-172)</br>[Update: 1.7.1 - Bug Fixes Only](#update-171---bug-fixes-only)</br>[Update: 1.7.0 - Threading the systems](#update-170---threading-the-systems)</br>[Update: 1.6.0](#update-160)</br>[Update: 1.5.0](#update-150)</br>[Update: 1.4.1 (4/10/2017) - First Public release of the library](#update-141-4102017---first-public-release-of-the-library)</br>[Update: 1.4.0 (3/20/2017)](#update-140-3202017)</br>[Update: 1.3.0 (1/29/2017)](#update-130-1292017)</br>[Update: 1.2.0 (12.31.2016)](#update-120-12312016)</br>[Update: 1.1.0](#update-110)</br>[Update: 1.0.0](#update-100)</br>[Update: 0.6.3](#update-063)</br>[Update: 0.6.2](#update-062)</br>[Update: 0.6.1-6](#update-061-6)</br>[Update: 0.5.1-6](#update-051-6)</br>[Update: 0.4.1](#update-041)</br>[Update: 0.3.0 - The update that started it all](#update-030---the-update-that-started-it-all)</br>[Update: EventManager 2.0.0](#update-eventmanager-200)</br>[Update: EventManager 1.2.0](#update-eventmanager-120)</br>[Update: EventManager 1.1.0](#update-eventmanager-110)</br>[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)</br>[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different)
# Update 15.3.0 - A world of connection
Full Update Showcase
```lua
multi, thread = require("multi"):init{print=true}
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
local conn = multi:newSystemThreadedConnection("conn"):init()
multi:newSystemThread("Thread_Test_1",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
conn(function()
print(THREAD:getName().." was triggered!")
end)
multi:mainloop()
end)
multi:newSystemThread("Thread_Test_2",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
conn(function(a,b,c)
print(THREAD:getName().." was triggered!",a,b,c)
end)
multi:newAlarm(2):OnRing(function()
print("Fire 2!!!")
conn:Fire(4,5,6)
THREAD.kill()
end)
multi:mainloop()
end)
conn(function(a,b,c)
print("Mainloop conn got triggered!",a,b,c)
end)
alarm = multi:newAlarm(1)
alarm:OnRing(function()
print("Fire 1!!!")
conn:Fire(1,2,3)
end)
alarm = multi:newAlarm(3):OnRing(function()
multi:newSystemThread("Thread_Test_3",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
conn(function(a,b,c)
print(THREAD:getName().." was triggered!",a,b,c)
end)
multi:newAlarm(2):OnRing(function()
print("Fire 3!!!")
conn:Fire(7,8,9)
end)
multi:mainloop()
end)
end)
multi:newSystemThread("Thread_Test_4",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
local conn2 = multi:newConnection()
multi:newAlarm(2):OnRing(function()
conn2:Fire()
end)
multi:newThread(function()
print("Conn Test!")
thread.hold(conn + conn2)
print("It held!")
end)
multi:mainloop()
end)
multi:mainloop()
```
Added
---
- `multi:newSystemThreadedConnection()`
Allows one to trigger connection events across threads. Works like how any connection would work. Supports all of the features, can even be `added` with non SystemThreadedConnections as demonstrated in the full showcase.
- `multi:newConnection():SetHelper(func)`
Sets the helper function that the connection object uses when creating connection links.
- `multi.ForEach(table, callback_function)`
Loops through the table and calls callback_function with each element of the array.
- If a name is not supplied when creating threads; a name is randomly generated. Unless sending through an established channel/queue you might not be able to easily init the object.
Changed
---
- `Connection:[connect, hasConnections, getConnection]` changed to be `Connection:[Connect, HasConnections, getConnections]`. This was done in an attempt to follow a consistent naming scheme. The old methods still will work to prevent old code breaking.
Removed
---
- Connection objects methods removed:
- holdUT(), HoldUT() -- With the way `thread.hold(conn)` interacts with connections this method was no longer needed. To emulate this use `multi.hold(conn)`. `multi.hold()` is able to emulate what `thread.hold()` outside of a thread, albeit with some drawbacks.
Fixed
---
- SystemThreaded Objects variables weren't consistent.
ToDo
---
- Work on network parallelism (I am really excited to start working on this. Not because it will have much use, but because it seems like a cool addition/project to work on. I just need time to actually do work on stuff)
# Update 15.2.1 - Bug fix
Fixed issue #41
---
# Update 15.2.0 - Upgrade Complete # Update 15.2.0 - Upgrade Complete
Full Update Showcase Full Update Showcase

View File

@ -1,9 +1,9 @@
commands = [[ commands = [[
mkdir luajit && python -m hererocks -j 2.1.0-beta3 -r latest --patch --compat all ./luajit && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi mkdir luajit && python -m hererocks -j 2.1.0-beta3 -r latest --patch --compat all ./luajit && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi && luarocks install lanes
mkdir lua5.1 && python -m hererocks -l 5.1 -r latest --patch --compat all ./lua5.1 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi mkdir lua5.1 && python -m hererocks -l 5.1 -r latest --patch --compat all ./lua5.1 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi && luarocks install lanes
mkdir lua5.2 && python -m hererocks -l 5.2 -r latest --patch --compat all ./lua5.2 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi mkdir lua5.2 && python -m hererocks -l 5.2 -r latest --patch --compat all ./lua5.2 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi && luarocks install lanes
mkdir lua5.3 && python -m hererocks -l 5.3 -r latest --patch --compat all ./lua5.3 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi mkdir lua5.3 && python -m hererocks -l 5.3 -r latest --patch --compat all ./lua5.3 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi && luarocks install lanes
mkdir lua5.4 && python -m hererocks -l 5.4 -r latest --patch --compat all ./lua5.4 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi mkdir lua5.4 && python -m hererocks -l 5.4 -r latest --patch --compat all ./lua5.4 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi && luarocks install lanes
]] ]]
function string.split (inputstr, sep) function string.split (inputstr, sep)
local sep = sep or "\n" local sep = sep or "\n"

View File

@ -58,15 +58,15 @@ multi.Priority_Very_Low = 16384
multi.Priority_Idle = 65536 multi.Priority_Idle = 65536
multi.PriorityResolve = { multi.PriorityResolve = {
[1]="Core", [1] = "Core",
[4]="Very High", [4] = "Very High",
[16]="High", [16] = "High",
[64]="Above Normal", [64] = "Above Normal",
[256]="Normal", [256] = "Normal",
[1024]="Below Normal", [1024] = "Below Normal",
[4096]="Low", [4096] = "Low",
[16384]="Very Low", [16384] = "Very Low",
[65536]="Idle", [65536] = "Idle",
} }
local PList = {multi.Priority_Core,multi.Priority_Very_High,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Very_Low,multi.Priority_Idle} local PList = {multi.Priority_Core,multi.Priority_Very_High,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Very_Low,multi.Priority_Idle}
@ -109,6 +109,12 @@ function multi:getStats()
end end
--Helpers --Helpers
function multi.ForEach(tab,func)
for i=1,#tab do
func(tab[i])
end
end
local ignoreconn = true local ignoreconn = true
function multi:newConnection(protect,func,kill) function multi:newConnection(protect,func,kill)
local c={} local c={}
@ -116,19 +122,20 @@ function multi:newConnection(protect,func,kill)
local lock = false local lock = false
c.callback = func c.callback = func
c.Parent=self c.Parent=self
setmetatable(c,{__call=function(self,...) setmetatable(c,{__call=function(self,...)
local t = ... local t = ...
if type(t)=="table" then if type(t)=="table" then
for i,v in pairs(t) do for i,v in pairs(t) do
if v==self then if v==self then
local ref = self:connect(select(2,...)) local ref = self:Connect(select(2,...))
ref.root_link = select(1,...) ref.root_link = select(1,...)
return ref return ref
end end
end end
return self:connect(...) return self:Connect(...)
else else
return self:connect(...) return self:Connect(...)
end end
end, end,
__add = function(c1,c2) __add = function(c1,c2)
@ -154,32 +161,18 @@ function multi:newConnection(protect,func,kill)
end) end)
return cn return cn
end}) end})
c.Type='connector' c.Type='connector'
c.func={} c.func={}
c.ID=0 c.ID=0
local protect=protect or false local protect=protect or false
local connections={} local connections={}
c.FC=0 c.FC=0
function c:hasConnections() function c:hasConnections()
return #call_funcs~=0 return #call_funcs~=0
end end
function c:holdUT(n)
local n=n or 0
self.waiting=true
local count=0
local id=self:connect(function()
count = count + 1
if n<=count then
self.waiting=false
end
end)
repeat
self.Parent:uManager()
until self.waiting==false
id:Destroy()
return self
end
c.HoldUT=c.holdUT
function c:getConnection(name,ignore) function c:getConnection(name,ignore)
if ignore then if ignore then
return connections[name] or CRef return connections[name] or CRef
@ -187,14 +180,17 @@ function multi:newConnection(protect,func,kill)
return connections[name] or self return connections[name] or self
end end
end end
function c:Lock() function c:Lock()
lock = true lock = true
return self return self
end end
function c:Unlock() function c:Unlock()
lock = false lock = false
return self return self
end end
if protect then if protect then
function c:Fire(...) function c:Fire(...)
if lock then return end if lock then return end
@ -208,6 +204,7 @@ function multi:newConnection(protect,func,kill)
end end
else else
function c:Fire(...) function c:Fire(...)
if lock then return end
for i=#call_funcs,1,-1 do for i=#call_funcs,1,-1 do
call_funcs[i](...) call_funcs[i](...)
if kill then if kill then
@ -216,48 +213,56 @@ function multi:newConnection(protect,func,kill)
end end
end end
end end
local fast = {} local fast = {}
function c:getConnections() function c:getConnections()
return call_funcs return call_funcs
end end
function c:fastMode() function c:fastMode()
function self:Fire(...) function self:Fire(...)
for i=1,#fast do for i=1,#fast do
fast[i](...) fast[i](...)
end end
end end
function self:connect(func) function self:Connect(func)
table.insert(fast,func) table.insert(fast,func)
end end
end end
function c:Bind(t) function c:Bind(t)
local temp = call_funcs local temp = call_funcs
call_funcs=t call_funcs=t
return temp return temp
end end
function c:Remove() function c:Remove()
local temp = call_funcs local temp = call_funcs
call_funcs={} call_funcs={}
return temp return temp
end end
local function conn_helper(self,func,name,num) local function conn_helper(self,func,name,num)
self.ID=self.ID+1 self.ID=self.ID+1
if num then if num then
table.insert(call_funcs,num,func) table.insert(call_funcs,num,func)
else else
table.insert(call_funcs,1,func) table.insert(call_funcs,1,func)
end end
local temp = { local temp = {
func=func, func=func,
Type="connector_link", Type="connector_link",
Parent=self, Parent=self,
connect = function(s,...) connect = function(s,...)
return self:connect(...) return self:Connect(...)
end end
} }
setmetatable(temp,{ setmetatable(temp,{
__call=function(s,...) __call=function(s,...)
return self:connect(...) return self:Connect(...)
end, end,
__index = function(t,k) __index = function(t,k)
if rawget(t,"root_link") then if rawget(t,"root_link") then
@ -272,17 +277,11 @@ function multi:newConnection(protect,func,kill)
rawset(t,k,v) rawset(t,k,v)
end, end,
}) })
function temp:Fire(...) function temp:Fire(...)
if lock then return end return call_funcs(...)
if protect then
local t=pcall(call_funcs,...)
if t then
return t
end
else
return call_funcs(...)
end
end end
function temp:Destroy() function temp:Destroy()
for i=#call_funcs,1,-1 do for i=#call_funcs,1,-1 do
if call_funcs[i]~=nil then if call_funcs[i]~=nil then
@ -294,15 +293,19 @@ function multi:newConnection(protect,func,kill)
end end
end end
end end
if name then if name then
connections[name]=temp connections[name]=temp
end end
if self.callback then if self.callback then
self.callback(temp) self.callback(temp)
end end
return temp return temp
end end
function c:connect(...)--func,name,num
function c:Connect(...)--func,name,num
local tab = {...} local tab = {...}
local funcs={} local funcs={}
for i=1,#tab do for i=1,#tab do
@ -320,8 +323,15 @@ function multi:newConnection(protect,func,kill)
return conn_helper(self,tab[1],tab[2],tab[3]) return conn_helper(self,tab[1],tab[2],tab[3])
end end
end end
c.Connect=c.connect
function c:SetHelper(func)
conn_helper = func
end
c.connect=c.Connect
c.GetConnection=c.getConnection c.GetConnection=c.getConnection
c.HasConnections = c.hasConnections
c.GetConnection = c.getConnection
if not(ignoreconn) then if not(ignoreconn) then
multi:create(c) multi:create(c)
end end
@ -1244,9 +1254,8 @@ local startme_len = 0
function thread:newThread(name,func,...) function thread:newThread(name,func,...)
multi.OnLoad:Fire() -- This was done incase a threaded function was called before mainloop/uManager was called multi.OnLoad:Fire() -- This was done incase a threaded function was called before mainloop/uManager was called
local func = func or name local func = func or name
if func == name then
if type(name) == "function" then name = name or multi.randomString(16)
name = "Thread#"..threadCount
end end
local c={nil,nil,nil,nil,nil,nil,nil} local c={nil,nil,nil,nil,nil,nil,nil}
local env = {self=c} local env = {self=c}
@ -2045,14 +2054,14 @@ function multi.print(...)
end end
end end
multi.GetType=multi.getType multi.GetType = multi.getType
multi.IsPaused=multi.isPaused multi.IsPaused = multi.isPaused
multi.IsActive=multi.isActive multi.IsActive = multi.isActive
multi.Reallocate=multi.Reallocate multi.Reallocate = multi.Reallocate
multi.ConnectFinal=multi.connectFinal multi.ConnectFinal = multi.connectFinal
multi.ResetTime=multi.SetTime multi.ResetTime = multi.SetTime
multi.IsDone=multi.isDone multi.IsDone = multi.isDone
multi.SetName = multi.setName multi.SetName = multi.setName
-- Special Events -- Special Events
local _os = os.exit local _os = os.exit

View File

@ -22,9 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local GLOBAL, THREAD = multi.integration.GLOBAL,multi.integration.THREAD if not (GLOBAL and THREAD) then
local GLOBAL, THREAD = multi.integration.GLOBAL,multi.integration.THREAD
else
lanes = require("lanes")
end
function multi:newSystemThreadedQueue(name) function multi:newSystemThreadedQueue(name)
local name = name or multi.randomString(16)
local c = {} local c = {}
c.Name = name
c.linda = lanes.linda() c.linda = lanes.linda()
function c:push(v) function c:push(v)
self.linda:send("Q", v) self.linda:send("Q", v)
@ -41,9 +47,12 @@ function multi:newSystemThreadedQueue(name)
GLOBAL[name or "_"] = c GLOBAL[name or "_"] = c
return c return c
end end
function multi:newSystemThreadedTable(name) function multi:newSystemThreadedTable(name)
local name = name or multi.randomString(16)
local c = {} local c = {}
c.link = lanes.linda() c.link = lanes.linda()
c.Name = name
setmetatable(c,{ setmetatable(c,{
__index = function(t,k) __index = function(t,k)
return c.link:get(k) return c.link:get(k)
@ -58,14 +67,15 @@ function multi:newSystemThreadedTable(name)
GLOBAL[name or "_"] = c GLOBAL[name or "_"] = c
return c return c
end end
function multi:newSystemThreadedJobQueue(n) function multi:newSystemThreadedJobQueue(n)
local c = {} local c = {}
c.cores = n or THREAD.getCores()*2 c.cores = n or THREAD.getCores()*2
c.OnJobCompleted = multi:newConnection() c.OnJobCompleted = multi:newConnection()
local funcs = multi:newSystemThreadedTable() local funcs = multi:newSystemThreadedTable():init()
local queueJob = multi:newSystemThreadedQueue() local queueJob = multi:newSystemThreadedQueue():init()
local queueReturn = multi:newSystemThreadedQueue() local queueReturn = multi:newSystemThreadedQueue():init()
local doAll = multi:newSystemThreadedQueue() local doAll = multi:newSystemThreadedQueue():init()
local ID=1 local ID=1
local jid = 1 local jid = 1
function c:isEmpty() function c:isEmpty()
@ -169,3 +179,120 @@ function multi:newSystemThreadedJobQueue(n)
end end
return c return c
end end
function multi:newSystemThreadedConnection(name)
local name = name or multi.randomString(16)
local c = {}
c.CONN = 0x00
c.TRIG = 0x01
c.PING = 0x02
c.PONG = 0x03
local function remove(a, b)
local ai = {}
local r = {}
for k,v in pairs(a) do ai[v]=true end
for k,v in pairs(b) do
if ai[v]==nil then table.insert(r,a[k]) end
end
return r
end
c.CID = THREAD.getID()
c.subscribe = multi:newSystemThreadedQueue("SUB_STC_"..self.Name):init()
c.Name = name
c.links = {} -- All triggers sent from main connection. When a connection is triggered on another thread, they speak to the main then send stuff out.
-- Locals will only live in the thread that creates the original object
local ping
local pong = function(link, links)
local res = thread.hold(function()
return link:peek()[1] == c.PONG
end,{sleep=3})
if not res then
self.links = remove(self.links, pings)
else
link:pop()
end
end
ping = thread:newFunction(function(self)
ping:Pause()
multi.ForEach(self.links, function(link) -- Sync new connections
link:push{self.PING}
multi:newThread("pong Thread", pong, link, links)
end)
thread.sleep(3)
ping:Resume()
end,false)
thread:newThread("STC_SUB_MAN"..name,function()
local item
while true do
thread.yield()
-- We need to check on broken connections
ping(c) -- Should return instantlly and process this in another thread
item = thread.hold(function() -- This will keep things held up until there is something to process
return c.subscribe:pop()
end)
if item[1] == c.CONN then
multi.ForEach(c.links, function(link) -- Sync new connections
item[2]:push{c.CONN, link}
end)
c.links[#c.links+1] = item[2]
elseif item[1] == c.TRIG then
c:Fire(unpack(item[2]))
c.proxy_conn:Fire(unpack(item[2]))
end
end
end)
--- ^^^ This will only exist in the init thread
function c:Fire(...)
local args = {...}
if self.CID == THREAD.getID() then -- Host Call
for _, link in pairs(self.links) do
link:push {self.TRIG, args}
end
else
self.subscribe:push {self.TRIG, args}
end
end
function c:init()
local multi, thread = require("multi"):init()
self.links = {}
self.proxy_conn = multi:newConnection()
local mt = getmetatable(self.proxy_conn)
setmetatable(self, {__index = self.proxy_conn, __call = function(t,func) self.proxy_conn(func) end, __add = mt.__add})
thread:newThread("STC_CONN_MAN"..name,function()
local item
local link_self_ref = multi:newSystemThreadedQueue()
self.subscribe:push{self.CONN, link_self_ref}
while true do
item = thread.hold(function()
return link_self_ref:peek()
end)
if item[1] == self.PING then
link_self_ref:push{self.PONG}
link_self_ref:pop()
elseif item[1] == self.CONN then
if item[2].Name ~= link_self_ref.Name then
table.insert(self.links, item[2])
end
link_self_ref:pop()
elseif item[1] == self.TRIG then
self.proxy_conn:Fire(unpack(item[2]))
link_self_ref:pop()
else
-- This shouldn't be the case
end
end
end)
return self
end
GLOBAL[name] = c
return c
end

View File

@ -62,6 +62,7 @@ function THREAD:newFunction(func,holdme)
end end
function multi:newSystemThread(name, func, ...) function multi:newSystemThread(name, func, ...)
local name = name or multi.randomString(16)
multi.InitSystemThreadErrorHandler() multi.InitSystemThreadErrorHandler()
local rand = math.random(1, 10000000) local rand = math.random(1, 10000000)
local return_linda = lanes.linda() local return_linda = lanes.linda()
@ -87,6 +88,7 @@ function multi:newSystemThread(name, func, ...)
}, },
priority=c.priority priority=c.priority
},function(...) },function(...)
require("multi.integration.lanesManager.extensions")
local has_error = true local has_error = true
return_linda:set("returns",{func(...)}) return_linda:set("returns",{func(...)})
has_error = false has_error = false

View File

@ -27,6 +27,7 @@ local multi, thread = require("multi").init()
GLOBAL = multi.integration.GLOBAL GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD THREAD = multi.integration.THREAD
function multi:newSystemThreadedQueue(name) function multi:newSystemThreadedQueue(name)
local name = name or multi.randomString(16)
local c = {} local c = {}
c.Name = name c.Name = name
local fRef = {"func",nil} local fRef = {"func",nil}
@ -64,10 +65,11 @@ function multi:newSystemThreadedQueue(name)
return c return c
end end
function multi:newSystemThreadedTable(name) function multi:newSystemThreadedTable(name)
local name = name or multi.randomString(16)
local c = {} local c = {}
c.name = name c.Name = name
function c:init() function c:init()
return THREAD.createTable(self.name) return THREAD.createTable(self.Name)
end end
THREAD.package(name,c) THREAD.package(name,c)
return c return c

View File

@ -25,6 +25,7 @@ local multi, thread = require("multi").init()
GLOBAL = multi.integration.GLOBAL GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD THREAD = multi.integration.THREAD
function multi:newSystemThreadedQueue(name) function multi:newSystemThreadedQueue(name)
local name = name or multi.randomString(16)
local c = {} local c = {}
c.Name = name c.Name = name
local fRef = {"func",nil} local fRef = {"func",nil}
@ -62,10 +63,11 @@ function multi:newSystemThreadedQueue(name)
return c return c
end end
function multi:newSystemThreadedTable(name) function multi:newSystemThreadedTable(name)
local name = name or multi.randomString(16)
local c = {} local c = {}
c.name = name c.Name = name
function c:init() function c:init()
return THREAD.createTable(self.name) return THREAD.createTable(self.Name)
end end
THREAD.package(name,c) THREAD.package(name,c)
return c return c

View File

@ -1,20 +1,72 @@
package.path = "./?/init.lua;?.lua;lua5.4/share/lua/?/init.lua;lua5.4/share/lua/?.lua;"..package.path package.path = "./?/init.lua;?.lua;lua5.2/share/lua/5.2/?/init.lua;lua5.2/share/lua/5.2/?.lua;"
package.cpath = "lua5.4/lib/lua/?/core.dll;"..package.cpath package.cpath = "lua5.2/lib/lua/5.2/?/core.dll;"
multi, thread = require("multi"):init{print=true} multi, thread = require("multi"):init{print=true}
GLOBAL, THREAD = require("multi.integration.lanesManager"):init() GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
test = THREAD:newFunction(function() local conn = multi:newSystemThreadedConnection("conn"):init()
PNT()
return 1,2 multi:newSystemThread("Thread_Test_1",function()
end,true) local multi, thread = require("multi"):init()
multi:newThread(function() local conn = GLOBAL["conn"]:init()
while true do conn(function()
print("...") print(THREAD:getName().." was triggered!")
thread.sleep(1) end)
end multi:mainloop()
end)
multi:newSystemThread("Thread_Test_2",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
conn(function(a,b,c)
print(THREAD:getName().." was triggered!",a,b,c)
end)
multi:newAlarm(2):OnRing(function()
print("Fire 2!!!")
conn:Fire(4,5,6)
THREAD.kill()
end)
multi:mainloop()
end)
conn(function(a,b,c)
print("Mainloop conn got triggered!",a,b,c)
end)
alarm = multi:newAlarm(1)
alarm:OnRing(function()
print("Fire 1!!!")
conn:Fire(1,2,3)
end)
alarm = multi:newAlarm(3):OnRing(function()
multi:newSystemThread("Thread_Test_3",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
conn(function(a,b,c)
print(THREAD:getName().." was triggered!",a,b,c)
end)
multi:newAlarm(2):OnRing(function()
print("Fire 3!!!")
conn:Fire(7,8,9)
end)
multi:mainloop()
end)
end)
multi:newSystemThread("Thread_Test_4",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
local conn2 = multi:newConnection()
multi:newAlarm(2):OnRing(function()
conn2:Fire()
end)
multi:newThread(function()
print("Conn Test!")
thread.hold(conn + conn2)
print("It held!")
end)
multi:mainloop()
end) end)
multi:newAlarm(.1):OnRing(function() os.exit() end)
print(test())
print("Hi!")
multi:mainloop() multi:mainloop()

33
test2.lua Normal file
View File

@ -0,0 +1,33 @@
function difference(a, b)
local ai = {}
local r = {}
local rr = {}
for k,v in pairs(a) do r[k] = v; ai[v]=true end
for k,v in pairs(b) do
if ai[v]==nil then table.insert(rr,r[k]) end
end
return rr
end
function remove(a, b)
local ai = {}
local r = {}
for k,v in pairs(a) do ai[v]=true end
for k,v in pairs(b) do
if ai[v]==nil then table.insert(r,a[k]) end
end
return r
end
function printtab(tab,msg)
print(msg or "TABLE")
for i,v in pairs(tab) do
print(i, v)
end
print("")
end
local tab1 = {1,2,3,4,5}
local tab2 = {3,4,5,6,7}
tab1 = remove(tab1,tab2)
printtab(tab1, "Table 1")
printtab(tab2, "Table 2")