Fixed system threaded connections Also added some features to monitor threads Each thread now has its own ID even the main thread which has an id of 0!
186 lines
4.5 KiB
Lua
186 lines
4.5 KiB
Lua
package.path="?/init.lua;?.lua;"..package.path
|
|
multi = require("multi")
|
|
local GLOBAL,THREAD = require("multi.integration.lanesManager").init()
|
|
nGLOBAL = require("multi.integration.networkManager").init()
|
|
local a
|
|
local clock = os.clock
|
|
function sleep(n) -- seconds
|
|
local t0 = clock()
|
|
while clock() - t0 <= n do end
|
|
end
|
|
master = multi:newMaster{
|
|
name = "Main", -- the name of the master
|
|
noBroadCast = true, -- if using the node manager, set this to true to avoid double connections
|
|
managerDetails = {"192.168.1.4",12345}, -- the details to connect to the node manager (ip,port)
|
|
}
|
|
master.OnError(function(name,err)
|
|
print(name.." has encountered an error: "..err)
|
|
end)
|
|
local connlist = {}
|
|
multi:newThread("NodeUpdater",function()
|
|
while true do
|
|
thread.sleep(1)
|
|
for i=1,#connlist do
|
|
conn = master:execute("TASK_MAN",connlist[i], multi:getTasksDetails())
|
|
end
|
|
end
|
|
end)
|
|
master.OnNodeConnected(function(name)
|
|
table.insert(connlist,name)
|
|
end)
|
|
multi.OnError(function(...)
|
|
print(...)
|
|
end)
|
|
|
|
|
|
local conncount = 0
|
|
function multi:newSystemThreadedConnection(name,protect)
|
|
conncount = conncount + 1
|
|
local c={}
|
|
c.name = name or error("You must provide a name for the connection object!")
|
|
c.protect = protect or false
|
|
c.idle = nil
|
|
local sThread=multi.integration.THREAD
|
|
local GLOBAL=multi.integration.GLOBAL
|
|
local connSync = multi:newSystemThreadedQueue(c.name.."_CONN_SYNC")
|
|
local connFire = multi:newSystemThreadedQueue(c.name.."_CONN_FIRE")
|
|
function c:init()
|
|
local multi = require("multi")
|
|
if love then -- lets make sure we don't reference up-values if using love2d
|
|
GLOBAL=_G.GLOBAL
|
|
sThread=_G.sThread
|
|
end
|
|
local conn = {}
|
|
conn.obj = multi:newConnection()
|
|
setmetatable(conn,{
|
|
__call=function(self,...)
|
|
return self:connect(...)
|
|
end
|
|
})
|
|
local ID = sThread.getID()
|
|
local sync = sThread.waitFor(self.name.."_CONN_SYNC"):init()
|
|
local fire = sThread.waitFor(self.name.."_CONN_FIRE"):init()
|
|
local connections = {}
|
|
if not multi.isMainThread then
|
|
connections = {0}
|
|
end
|
|
sync:push{"INIT",ID} -- Register this as an active connection!
|
|
function conn:connect(func)
|
|
return self.obj(func)
|
|
end
|
|
function conn:holdUT(n)
|
|
self.obj:holdUT(n)
|
|
end
|
|
function conn:Remove()
|
|
self.obj:Remove()
|
|
end
|
|
function conn:Fire(...)
|
|
for i = 1,#connections do
|
|
fire:push{connections[i],ID,{...}}
|
|
end
|
|
end
|
|
-- FIRE {TO,FROM,{ARGS}}
|
|
local data
|
|
multi:newLoop(function()
|
|
data = fire:peek()
|
|
if type(data)=="table" and data[1]==ID then
|
|
if data[2]==ID and conn.IgnoreSelf then
|
|
fire:pop()
|
|
return
|
|
end
|
|
fire:pop()
|
|
conn.obj:Fire(unpack(data[3]))
|
|
end
|
|
-- We need to hangle syncs here as well
|
|
data = sync:peek()
|
|
if data~=nil and data[1]=="SYNCA" and data[2]==ID then
|
|
sync:pop()
|
|
table.insert(connections,data[3])
|
|
end
|
|
if type(data)=="table" and data[1]=="SYNCR" and data[2]==ID then
|
|
sync:pop()
|
|
for i=1,#connections do
|
|
if connections[i] == data[3] then
|
|
table.remove(connections,i)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
return conn
|
|
end
|
|
local cleanUp = {}
|
|
multi.OnSystemThreadDied(function(ThreadID)
|
|
for i=1,#syncs do
|
|
connSync:push{"SYNCR",syncs[i],ThreadID}
|
|
end
|
|
cleanUp[ThreadID] = true
|
|
end)
|
|
multi:newThread(c.name.." Connection Handler",function()
|
|
local data
|
|
local clock = os.clock
|
|
local syncs = {}
|
|
while true do
|
|
if not c.idle then
|
|
thread.sleep(.1)
|
|
else
|
|
if clock() - c.idle >= 15 then
|
|
c.idle = nil
|
|
end
|
|
thread.skip()
|
|
end
|
|
data = connSync:peek()
|
|
if data~= nil and data[1]=="INIT" then
|
|
connSync:pop()
|
|
c.idle = clock()
|
|
table.insert(syncs,data[2])
|
|
for i=1,#syncs do
|
|
connSync:push{"SYNCA",syncs[i],data[2]}
|
|
end
|
|
end
|
|
data = connFire:peek()
|
|
if data~=nil and cleanUp[data[1]] then
|
|
local meh = data[1]
|
|
connFire:pop() -- lets remove dead thread stuff
|
|
multi:newAlarm(15):OnRing(function(a)
|
|
cleanUp[meh] = nil
|
|
end)
|
|
end
|
|
end
|
|
end)
|
|
GLOBAL[c.name]=c
|
|
return c
|
|
end
|
|
|
|
|
|
local conn = multi:newSystemThreadedConnection("conn"):init()
|
|
conn(function(...)
|
|
print("MAIN",...)
|
|
end)
|
|
conn.IgnoreSelf = true
|
|
multi:newSystemThread("meh",function()
|
|
local multi = require("multi")
|
|
local conn = THREAD.waitFor("conn"):init()
|
|
conn.IgnoreSelf = true
|
|
conn(function(...)
|
|
print("THREAD:",...)
|
|
end)
|
|
multi:newAlarm(1):OnRing(function(a)
|
|
conn:Fire("Does this work?")
|
|
a:Destroy()
|
|
end)
|
|
multi.OnError(function(...)
|
|
print(...)
|
|
end)
|
|
multi:mainloop()
|
|
end).OnError(function(...)
|
|
print(...)
|
|
end)
|
|
multi:newAlarm(2):OnRing(function(a)
|
|
conn:Fire("What about this one?")
|
|
a:Destroy()
|
|
end)
|
|
multi:mainloop{
|
|
protect = false,
|
|
--~ print = true
|
|
}
|