ST - connections work

Finally, but more bugs found
Need to fix, sigh why node manager no work in love2d. Both luajit, both luasocket, both net and multi library. works in non love, but not love I wanna just melt, there is no reason why no work
This commit is contained in:
Ryan Ward 2019-02-09 23:32:26 -05:00
parent 4272397678
commit 391625674a
6 changed files with 222 additions and 251 deletions

View File

@ -73,6 +73,9 @@ Added:
- THREAD.getID() -- returns a unique ID for the current thread. This varaiable is visible to the main thread as well by accessing it through the returned thread object. OBJ.Id Do not confuse this with thread.* this refers to the system threading interface. Each thread, including the main thread has a threadID the main thread has an ID of 0! - THREAD.getID() -- returns a unique ID for the current thread. This varaiable is visible to the main thread as well by accessing it through the returned thread object. OBJ.Id Do not confuse this with thread.* this refers to the system threading interface. Each thread, including the main thread has a threadID the main thread has an ID of 0!
- multi.print(...) works like normal print, but only prints if the setting print is set to true - multi.print(...) works like normal print, but only prints if the setting print is set to true
- setting: `print` enables multi.print() to work - setting: `print` enables multi.print() to work
- STC: IgnoreSelf defaults to false, if true a Fire command will not be sent to the self
- STC: OnConnectionAdded(function(connID)) -- Is fired when a connection is added you can use STC:FireTo(id,...) to trigger a specific connection. Works like the named non threaded connections, only the id's are genereated for you.
- STC: FireTo(id,...) -- Described above.
```lua ```lua
package.path="?/init.lua;?.lua;"..package.path package.path="?/init.lua;?.lua;"..package.path

View File

@ -28,7 +28,7 @@ multi.Version = "13.0.0"
multi._VERSION = "13.0.0" multi._VERSION = "13.0.0"
multi.stage = "stable" multi.stage = "stable"
multi.__index = multi multi.__index = multi
multi.Name = "multi.Root" multi.Name = "multi.root"
multi.Mainloop = {} multi.Mainloop = {}
multi.Garbage = {} multi.Garbage = {}
multi.ender = {} multi.ender = {}
@ -121,7 +121,7 @@ function multi:enableLoadDetection()
local t = os.clock() local t = os.clock()
local stop = false local stop = false
temp:benchMark(.01):OnBench(function(time,steps) temp:benchMark(.01):OnBench(function(time,steps)
stop = steps*1.1 stop = steps
end) end)
while not stop do while not stop do
temp:uManager() temp:uManager()
@ -135,6 +135,7 @@ function multi:setLoad(n)
end end
local busy = false local busy = false
local lastVal = 0 local lastVal = 0
local bb = 0
function multi:getLoad() function multi:getLoad()
if not multi.maxSpd then multi:enableLoadDetection() end if not multi.maxSpd then multi:enableLoadDetection() end
if busy then return lastVal end if busy then return lastVal end
@ -143,6 +144,7 @@ function multi:getLoad()
local bench local bench
multi:benchMark(.01):OnBench(function(time,steps) multi:benchMark(.01):OnBench(function(time,steps)
bench = steps bench = steps
bb = steps
end) end)
thread.hold(function() thread.hold(function()
return bench return bench
@ -154,6 +156,7 @@ function multi:getLoad()
local bench local bench
multi:benchMark(.01):OnBench(function(time,steps) multi:benchMark(.01):OnBench(function(time,steps)
bench = steps bench = steps
bb = steps
end) end)
while not bench do while not bench do
multi:uManager() multi:uManager()
@ -165,7 +168,7 @@ function multi:getLoad()
if val<0 then val = 0 end if val<0 then val = 0 end
if val > 100 then val = 100 end if val > 100 then val = 100 end
lastVal = val lastVal = val
return val return val,bb*100
end end
function multi:setDomainName(name) function multi:setDomainName(name)
self[name]={} self[name]={}
@ -197,6 +200,13 @@ function multi:setPriority(s)
end end
self.solid = true self.solid = true
end end
if not self.PrioritySet then
self.defPriority = self.Priority
self.PrioritySet = true
end
end
function multi:ResetPriority()
self.Priority = self.defPriority
end end
-- System -- System
function os.getOS() function os.getOS()
@ -345,20 +355,24 @@ function multi:getTasksDetails(t)
dat2 = dat2.."<SystemThread: "..multi.SystemThreads[i].Name.." | "..os.clock()-multi.SystemThreads[i].creationTime..">\n" dat2 = dat2.."<SystemThread: "..multi.SystemThreads[i].Name.." | "..os.clock()-multi.SystemThreads[i].creationTime..">\n"
end end
end end
local load,steps = multi:getLoad()
if multi.scheduler then if multi.scheduler then
for i=1,#multi.scheduler.Threads do for i=1,#multi.scheduler.Threads do
dat = dat .. "<THREAD: "..multi.scheduler.Threads[i].Name.." | "..os.clock()-multi.scheduler.Threads[i].creationTime..">\n" dat = dat .. "<THREAD: "..multi.scheduler.Threads[i].Name.." | "..os.clock()-multi.scheduler.Threads[i].creationTime..">\n"
end end
return "Load on "..ProcessName[self.Type=="process"].."<"..(self.Name or "Unnamed")..">"..": "..multi.Round(multi:getLoad(),2).."%\nMemory Usage: "..math.ceil(collectgarbage("count")).." KB\nThreads Running: "..#multi.scheduler.Threads.."\nSystemThreads Running: "..#(multi.SystemThreads or {}).."\nPriority Scheme: "..priorityTable[multi.defaultSettings.priority or 0].."\n\n"..s.."\n\n"..dat..dat2 return "Load on "..ProcessName[self.Type=="process"].."<"..(self.Name or "Unnamed")..">"..": "..multi.Round(load,2).."%\nCycles Per Second Per Task: "..steps.."\nMemory Usage: "..math.ceil(collectgarbage("count")).." KB\nThreads Running: "..#multi.scheduler.Threads.."\nSystemThreads Running: "..#(multi.SystemThreads or {}).."\nPriority Scheme: "..priorityTable[multi.defaultSettings.priority or 0].."\n\n"..s.."\n\n"..dat..dat2
else else
return "Load on "..ProcessName[self.Type=="process"].."<"..(self.Name or "Unnamed")..">"..": "..multi.Round(multi:getLoad(),2).."%\nMemory Usage: "..math.ceil(collectgarbage("count")).." KB\nThreads Running: 0\nPriority Scheme: "..priorityTable[multi.defaultSettings.priority or 0].."\n\n"..s..dat2 return "Load on "..ProcessName[self.Type=="process"].."<"..(self.Name or "Unnamed")..">"..": "..multi.Round(load,2).."%\nCycles Per Second Per Task: "..steps.."\n\nMemory Usage: "..math.ceil(collectgarbage("count")).." KB\nThreads Running: 0\nPriority Scheme: "..priorityTable[multi.defaultSettings.priority or 0].."\n\n"..s..dat2
end end
elseif t == "t" or t == "table" then elseif t == "t" or t == "table" then
local load,steps = multi:getLoad()
str = { str = {
ProcessName = (self.Name or "Unnamed"),
ThreadCount = #multi.scheduler.Threads, ThreadCount = #multi.scheduler.Threads,
MemoryUsage = math.ceil(collectgarbage("count")).." KB", MemoryUsage = math.ceil(collectgarbage("count")).." KB",
PriorityScheme = priorityTable[multi.defaultSettings.priority or 0], PriorityScheme = priorityTable[multi.defaultSettings.priority or 0],
SystemLoad = multi.Round(multi:getLoad(),2) SystemLoad = multi.Round(load,2),
CyclesPerSecondPerTask = steps,
} }
str.threads = {} str.threads = {}
str.systemthreads = {} str.systemthreads = {}
@ -970,7 +984,7 @@ end
function multi:newAlarm(set) function multi:newAlarm(set)
local c=self:newBase() local c=self:newBase()
c.Type='alarm' c.Type='alarm'
c.Priority=self.Priority_Low c:setPriority("Low")
c.set=set or 0 c.set=set or 0
local count = 0 local count = 0
local t = clock() local t = clock()
@ -1174,7 +1188,7 @@ function multi:newTStep(start,reset,count,set)
local c=self:newBase() local c=self:newBase()
think=1 think=1
c.Type='tstep' c.Type='tstep'
c.Priority=self.Priority_Low c:setPriority("Low")
c.start=start or 1 c.start=start or 1
local reset = reset or math.huge local reset = reset or math.huge
c.endAt=reset c.endAt=reset
@ -1266,7 +1280,7 @@ function multi:newTimeStamper()
["12"] = 31, ["12"] = 31,
} }
c.Type='timestamper' c.Type='timestamper'
c.Priority=self.Priority_Idle c:setPriority("Idle")
c.hour = {} c.hour = {}
c.minute = {} c.minute = {}
c.second = {} c.second = {}
@ -1886,8 +1900,8 @@ function multi:mainloop(settings)
local PS=self local PS=self
local PStep = 1 local PStep = 1
local autoP = 0 local autoP = 0
local solid local solid,sRef
local sRef local cc=0
while mainloopActive do while mainloopActive do
if next then if next then
local DD = table.remove(next,1) local DD = table.remove(next,1)
@ -1947,8 +1961,12 @@ function multi:mainloop(settings)
PStep=0 PStep=0
end end
elseif priority == 3 then elseif priority == 3 then
tt = clock()-t cc=cc+1
t = clock() if cc == 1000 then
tt = clock()-t
t = clock()
cc=0
end
for _D=#Loop,1,-1 do for _D=#Loop,1,-1 do
if Loop[_D] then if Loop[_D] then
if Loop[_D].Priority == p_c or (Loop[_D].Priority == p_h and tt<.5) or (Loop[_D].Priority == p_an and tt<.125) or (Loop[_D].Priority == p_n and tt<.063) or (Loop[_D].Priority == p_bn and tt<.016) or (Loop[_D].Priority == p_l and tt<.003) or (Loop[_D].Priority == p_i and tt<.001) then if Loop[_D].Priority == p_c or (Loop[_D].Priority == p_h and tt<.5) or (Loop[_D].Priority == p_an and tt<.125) or (Loop[_D].Priority == p_n and tt<.063) or (Loop[_D].Priority == p_bn and tt<.016) or (Loop[_D].Priority == p_l and tt<.003) or (Loop[_D].Priority == p_i and tt<.001) then

View File

@ -168,6 +168,9 @@ end
function sThread.getName() function sThread.getName()
return __THREADNAME__ return __THREADNAME__
end end
function sThread.getID()
return THREAD_ID
end
function sThread.kill() function sThread.kill()
error("Thread was killed!") error("Thread was killed!")
end end
@ -196,6 +199,7 @@ func=loadDump([=[INSERT_USER_CODE]=])(unpack(tab))
multi:mainloop() multi:mainloop()
]] ]]
GLOBAL={} -- Allow main thread to interact with these objects as well GLOBAL={} -- Allow main thread to interact with these objects as well
_G.THREAD_ID = 0
__proxy__={} __proxy__={}
setmetatable(GLOBAL,{ setmetatable(GLOBAL,{
__index=function(t,k) __index=function(t,k)
@ -215,6 +219,7 @@ setmetatable(GLOBAL,{
THREAD={} -- Allow main thread to interact with these objects as well THREAD={} -- Allow main thread to interact with these objects as well
multi.integration.love2d.mainChannel=love.thread.getChannel("__MainChan__") multi.integration.love2d.mainChannel=love.thread.getChannel("__MainChan__")
isMainThread=true isMainThread=true
multi.SystemThreads = {}
function THREAD.getName() function THREAD.getName()
return __THREADNAME__ return __THREADNAME__
end end
@ -299,16 +304,19 @@ local function randomString(n)
end end
return str return str
end end
local count = 0 local count = 1
local livingThreads = {}
function multi:newSystemThread(name,func,...) -- the main method function multi:newSystemThread(name,func,...) -- the main method
multi.InitSystemThreadErrorHandler()
local c={} local c={}
c.name=name c.name=name
c.Name = name c.Name = name
c.ID=c.name.."<ID|"..randomString(8)..">" c.ID=c.name.."<ID|"..randomString(8)..">"
c.Id=count c.Id=count
count = count + 1 count = count + 1
livingThreads[count] = {true,name}
c.thread=love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func))) c.thread=love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func)))
c.thread:start(c.ID,c.name,,...) c.thread:start(c.ID,c.name,THREAD_ID,...)
function c:kill() function c:kill()
multi.integration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__" multi.integration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__"
end end
@ -341,8 +349,7 @@ end
__channels__={} __channels__={}
multi.integration.GLOBAL=GLOBAL multi.integration.GLOBAL=GLOBAL
multi.integration.THREAD=THREAD multi.integration.THREAD=THREAD
updater=multi:newUpdater() updater=multi:newLoop(function(self)
updater:OnUpdate(function(self)
local data=multi.integration.love2d.mainChannel:pop() local data=multi.integration.love2d.mainChannel:pop()
while data do while data do
if type(data)=="string" then if type(data)=="string" then
@ -373,6 +380,35 @@ updater:OnUpdate(function(self)
data=multi.integration.love2d.mainChannel:pop() data=multi.integration.love2d.mainChannel:pop()
end end
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") require("multi.integration.shared")
multi.print("Integrated Love2d!") multi.print("Integrated Love2d!")
return { return {

View File

@ -112,89 +112,138 @@ function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a chann
end end
return c return c
end end
-- NEEDS WORK
-- function multi:newSystemThreadedConnection(name,protect) function multi:newSystemThreadedConnection(name,protect)
-- local c={} local c={}
-- local sThread=multi.integration.THREAD c.name = name or error("You must provide a name for the connection object!")
-- local GLOBAL=multi.integration.GLOBAL c.protect = protect or false
-- c.name = name or error("You must supply a name for this object!") c.idle = nil
-- c.protect = protect or false local sThread=multi.integration.THREAD
-- c.count = 0 local GLOBAL=multi.integration.GLOBAL
-- multi:newSystemThreadedQueue(name.."THREADED_CALLFIRE"):init() local connSync = multi:newSystemThreadedQueue(c.name.."_CONN_SYNC")
-- local qsm = multi:newSystemThreadedQueue(name.."THREADED_CALLSYNCM"):init() local connFire = multi:newSystemThreadedQueue(c.name.."_CONN_FIRE")
-- local qs = multi:newSystemThreadedQueue(name.."THREADED_CALLSYNC"):init() function c:init()
-- function c:init() local multi = require("multi")
-- _G.__Needs_Multi = true if love then -- lets make sure we don't reference up-values if using love2d
-- local multi = require("multi") GLOBAL=_G.GLOBAL
-- if multi:getPlatform()=="love2d" then sThread=_G.sThread
-- GLOBAL=_G.GLOBAL end
-- sThread=_G.sThread local conn = {}
-- end conn.obj = multi:newConnection()
-- local conns = 0 setmetatable(conn,{
-- local qF = sThread.waitFor(self.name.."THREADED_CALLFIRE"):init() __call=function(self,...)
-- local qSM = sThread.waitFor(self.name.."THREADED_CALLSYNCM"):init() return self:connect(...)
-- local qS = sThread.waitFor(self.name.."THREADED_CALLSYNC"):init() end
-- qSM:push("OK") })
-- local conn = {} local ID = sThread.getID()
-- conn.obj = multi:newConnection(self.protect) local sync = sThread.waitFor(self.name.."_CONN_SYNC"):init()
-- setmetatable(conn,{__call=function(self,...) return self:connect(...) end}) local fire = sThread.waitFor(self.name.."_CONN_FIRE"):init()
-- function conn:connect(func) local connections = {}
-- return self.obj(func) if not multi.isMainThread then
-- end connections = {0}
-- function conn:holdUT(n) end
-- self.obj:holdUT(n) sync:push{"INIT",ID} -- Register this as an active connection!
-- end function conn:connect(func)
-- function conn:Remove() return self.obj(func)
-- self.obj:Remove() end
-- end function conn:holdUT(n)
-- function conn:Fire(...) self.obj:holdUT(n)
-- local args = {multi.randomString(8),...} end
-- for i = 1, conns do function conn:Remove()
-- qF:push(args) self.obj:Remove()
-- end end
-- end function conn:Fire(...)
-- local lastID = "" for i = 1,#connections do
-- local lastCount = 0 fire:push{connections[i],ID,{...}}
-- multi:newThread("syncer",function() end
-- while true do end
-- thread.skip(1) function conn:FireTo(to,...)
-- local fire = qF:peek() local good = false
-- local count = qS:peek() for i = 1,#connections do
-- if fire and fire[1]~=lastID then if connections[i]==to then
-- lastID = fire[1] good = true
-- qF:pop() break
-- table.remove(fire,1) end
-- conn.obj:Fire(unpack(fire)) end
-- end if not good then return multi.print("NonExisting Connection!") end
-- if count and count[1]~=lastCount then fire:push{to,ID,{...}}
-- conns = count[2] end
-- lastCount = count[1] -- FIRE {TO,FROM,{ARGS}}
-- qs:pop() local data
-- end local clock = os.clock
-- end conn.OnConnectionAdded = multi:newConnection()
-- end) multi:newLoop(function()
-- return conn data = fire:peek()
-- end if type(data)=="table" and data[1]==ID then
-- multi:newThread("connSync",function() if data[2]==ID and conn.IgnoreSelf then
-- while true do fire:pop()
-- thread.skip(1) return
-- local syncIN = qsm:pop() end
-- if syncIN then fire:pop()
-- if syncIN=="OK" then conn.obj:Fire(unpack(data[3]))
-- c.count = c.count + 1 end
-- else data = sync:peek()
-- c.count = c.count - 1 if data~=nil and data[1]=="SYNCA" and data[2]==ID then
-- end sync:pop()
-- local rand = math.random(1,1000000) multi.nextStep(function()
-- for i = 1, c.count do conn.OnConnectionAdded:Fire(data[3])
-- qs:push({rand,c.count}) end)
-- end table.insert(connections,data[3])
-- end end
-- end if type(data)=="table" and data[1]=="SYNCR" and data[2]==ID then
-- end) sync:pop()
-- GLOBAL[name]=c for i=1,#connections do
-- return c if connections[i] == data[3] then
-- end table.remove(connections,i)
end
end
end
end):setName("STConn.syncer")
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(.5)
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
function multi:SystemThreadedBenchmark(n) function multi:SystemThreadedBenchmark(n)
n=n or 1 n=n or 1
local cores=multi.integration.THREAD.getCores() local cores=multi.integration.THREAD.getCores()

12
sample-nodeManager.lua Normal file
View File

@ -0,0 +1,12 @@
package.path="?/init.lua;?.lua;"..package.path
multi = require("multi")
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
nGLOBAL = require("multi.integration.networkManager").init()
multi:nodeManager(12345) -- Host a node manager on port: 12345
print("Node Manager Running...")
settings = {
priority = 0, -- 1 or 2
protect = false,
}
multi:mainloop(settings)
-- Thats all you need to run the node manager, everything else is done automatically

155
test.lua
View File

@ -11,7 +11,7 @@ end
master = multi:newMaster{ master = multi:newMaster{
name = "Main", -- the name of the master name = "Main", -- the name of the master
noBroadCast = true, -- if using the node manager, set this to true to avoid double connections 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) managerDetails = {"localhost",12345}, -- the details to connect to the node manager (ip,port)
} }
master.OnError(function(name,err) master.OnError(function(name,err)
print(name.." has encountered an error: "..err) print(name.." has encountered an error: "..err)
@ -21,165 +21,18 @@ multi:newThread("NodeUpdater",function()
while true do while true do
thread.sleep(1) thread.sleep(1)
for i=1,#connlist do for i=1,#connlist do
conn = master:execute("TASK_MAN",connlist[i], multi:getTasksDetails()) master:execute("TASK_MAN",connlist[i], multi:getTasksDetails())
end end
end end
end) end)
master.OnNodeConnected(function(name) master.OnNodeConnected(function(name)
print("Connected to the node")
table.insert(connlist,name) table.insert(connlist,name)
end) end)
multi.OnError(function(...) multi.OnError(function(...)
print(...) print(...)
end) 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{ multi:mainloop{
protect = false, protect = false,
--~ print = true print = true
} }