GLOBAL table works

This commit is contained in:
Ryan Ward 2018-06-20 09:30:05 -04:00
parent de2b3ee100
commit 644044901d
4 changed files with 154 additions and 78 deletions

View File

@ -44,6 +44,10 @@ multi.clock = os.clock
multi.time = os.time
multi.LinkedPath = multi
multi.isRunning = false
multi.defaultSettings = {
priority = 0,
protect = false,
}
--Do not change these ever...Any other number will not work (Unless you are using enablePriority2())
multi.Priority_Core = 1
multi.Priority_High = 4
@ -590,7 +594,7 @@ function multi:newConnection(protect)
end
end)
repeat
self.Parent:uManager()
self.Parent:uManager(multi.defaultSettings)
until self.waiting==false
id:Destroy()
end
@ -747,6 +751,7 @@ function multi:newCondition(func)
end
multi.NewCondition=multi.newCondition
function multi:mainloop(settings)
multi.defaultSettings = settings or multi.defaultSettings
if not multi.isRunning then
local protect = false
local priority = false
@ -838,11 +843,12 @@ function multi:uManager(settings)
settings.preLoop(self)
end
end
multi.defaultSettings = settings or multi.defaultSettings
self.uManager=self.uManagerRef
end
function multi:uManagerRef(settings)
if self.Active then
if settings.priority==1 then
if multi.defaultSettings.priority==1 then
local Loop=self.Mainloop
local PS=self
for _D=#Loop,1,-1 do
@ -851,7 +857,7 @@ function multi:uManagerRef(settings)
if (PS.PList[P])%Loop[_D].Priority==0 then
if Loop[_D].Active then
self.CID=_D
if not settings.protect then
if not multi.defaultSettings.protect then
Loop[_D]:Act()
else
local status, err=pcall(Loop[_D].Act,Loop[_D])
@ -865,7 +871,7 @@ function multi:uManagerRef(settings)
end
end
end
elseif settings.priority==2 then
elseif multi.defaultSettings.priority==2 then
local Loop=self.Mainloop
local PS=self
for _D=#Loop,1,-1 do
@ -873,7 +879,7 @@ function multi:uManagerRef(settings)
if (PS.PStep)%Loop[_D].Priority==0 then
if Loop[_D].Active then
self.CID=_D
if not settings.protect then
if not multi.defaultSettings.protect then
Loop[_D]:Act()
else
local status, err=pcall(Loop[_D].Act,Loop[_D])
@ -896,7 +902,7 @@ function multi:uManagerRef(settings)
if Loop[_D] then
if Loop[_D].Active then
self.CID=_D
if not settings.protect then
if not multi.defaultSettings.protect then
Loop[_D]:Act()
else
local status, err=pcall(Loop[_D].Act,Loop[_D])

View File

@ -14,6 +14,7 @@ local CMD_INITNODE = 0x05
local CMD_INITMASTER = 0x06
local CMD_GLOBAL = 0x07
local CMD_LOAD = 0x08
local CMD_CALL = 0x09
local char = string.char
local byte = string.byte
@ -45,24 +46,10 @@ end
function queue:peek()
return self[1]
end
local queues = {}
multi.OnNetQueue = multi:newConnection()
multi.OnGUpdate = multi:newConnection()
-- internal global system
local GLOBAL = {}
local THREAD = {}
local PROXY = {}
setmetatable(GLOBAL,{
__index = function(t,k)
return PROXY[k]
end,
__newindex = function(t,k,v)
local v = v
PROXY[k] = v
multi.OnGUpdate:Fire(k,packData(v))
end
})
-- Managing the data that goes through the system
local function packData(data)
-- returns the data that was sterilized
@ -104,6 +91,20 @@ local function resolveData(data)
end
end
-- internal global system
local GLOBAL = {}
local PROXY = {}
setmetatable(GLOBAL,{
__index = function(t,k)
return PROXY[k]
end,
__newindex = function(t,k,v)
local v = v
PROXY[k] = v
multi.OnGUpdate:Fire(k,packData(v))
end
})
-- The main driving force of the network manager: Nodes
function multi:newNode(name,settings)
-- Here we have to use the net library to broadcast our node across the network
@ -114,7 +115,8 @@ function multi:newNode(name,settings)
node.server = net:newUDPServer(0) -- hosts the node using the default port
node.port = node.server.port
node.connections = net.ClientCache
node.queue = newQueue()
node.queue = queue:newQueue()
node.loadRate=1
if settings then
if settings.crossTalk then
net.OnCastedClientInfo(function(client,name,ip,port)
@ -157,30 +159,35 @@ function multi:newNode(name,settings)
local name,d=dat:match("(.-)|(.+)")
multi.OnNetQueue:Fire(name,d)
elseif cmd == CMD_TASK then
local args,func = dat:match("(.-)|(.+)")
func = resolveData(func)
args = resolveData(args)
func(unpack(args))
elseif cmd == CMD_INITNODE then
print("Connected with another node!")
node.nodes[dat]={server,ip,port}
node.connections[dat]={server,ip,port}
multi.OnGUpdate(function(k,v)
server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port)
end)
-- set this up
end)-- set this up
elseif cmd == CMD_INITMASTER then
print("Connected to the master!")
node.masters[dat]={server,ip,port}
node.connections[dat]={server,ip,port}
multi.OnGUpdate(function(k,v)
server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port)
end)
-- set this up
end)-- set this up
multi:newTLoop(function()
server:send(ip,char(CMD_LOAD)..node.name.."|"..multi:getLoad(),port)
end,node.loadRate)
server:send(ip,char(CMD_LOAD)..node.name.."|"..multi:getLoad(),port)
elseif cmd == CMD_GLOBAL then
local k,v = dat:match("(.-)|(.+)")
PROXY[k]=resolveData(v)
elseif cmd == CMD_LOAD then
local load = multi:getLoad()
server:send(ip,node.name.."|"..load,port)
end
end)
function node:sendTo(name,data)
function node:sendToMaster(name,data)
self.connections[name]:send(data)
end
function node:sendToNode(name,data)
self.connections[name]:send(data)
end
node.server:broadcast("NODE_"..name)
@ -188,46 +195,79 @@ function multi:newNode(name,settings)
end
-- Masters
function multi:newMaster(name,settings) -- You will be able to have more than one master connecting to a node if that is what you want to do. I want you to be able to have the freedom to code any way that you want to code.
function multi:newMaster(name,settings) -- You will be able to have more than one master connecting to node(s) if that is what you want to do. I want you to be able to have the freedom to code any way that you want to code.
local master = {}
master.name = name
master.conn = multi:newConnection()
master.conn2 = multi:newConnection()
master.OnFirstNodeConnected = multi:newConnection()
master.queue = queue:newQueue()
master.connections = net.ClientCache -- Link to the client cache that is created on the net interface
function master:newNetworkThread(name,func) -- If name specified then it will be sent to the specified node! Otherwise the least worked node will get the job
local fData = CMD_TASK..packData(func)
master.loads = {}
master.trigger = multi:newFunction(function(self)
master.OnFirstNodeConnected:Fire()
self:Pause()
end)
function master:newNetworkThread(tname,name,func,...) -- If name specified then it will be sent to the specified node! Otherwise the least worked node will get the job
local fData = packData(func)
local tab = {...}
local aData = ""
if #tab~=o then
aData = (packData{...}).."|"
else
aData = (packData{1,1}).."|"
end
if not name then
local name = self:getFreeNode()
self:sendTo(name,data)
if not name then
name = self:getRandomNode()
end
if name==nil then
multi:newTLoop(function(loop)
if name~=nil then
print("Readying Func")
self:sendTo(name,char(CMD_TASK)..aData..fData)
loop:Desrtoy()
end
end,.1)
else
self:sendTo(name,char(CMD_TASK)..aData..fData)
end
else
local name = "NODE_"..name
self:sendTo(name,data)
self:sendTo(name,char(CMD_TASK)..aData..fData)
end
end
function master:sendTo(name,data)
self.connections["NODE_"..name]:send(data)
if self.connections["NODE_"..name]==nil then
multi:newTLoop(function(loop)
if self.connections["NODE_"..name]~=nil then
self.connections["NODE_"..name]:send(data)
loop:Desrtoy()
end
end,.1)
else
self.connections["NODE_"..name]:send(data)
end
end
function master:getFreeNode()
local count = 0
for i,v in pairs(self.connections)
v:send(CMD_LOAD)
count=count+1
end
local list = {}
local ref = self.conn(function(name,load)
list[#list+1]={load,name}
end)
self.conn:holdUT(count) -- we need to wait until we got a response from each node
ref:Remove() -- We need to destroy that connection that we made
local min = math.huge
local ref
for i = 1,#list do
if list[i][1]<min then
min = list[i][1]
ref = list[i][2]
local refO
for i,v in pairs(master.loads) do
if v<min then
min = v
refO = i
end
end
return ref
return refO
end
function master:getRandomNode()
local list = {}
for i,v in pairs(master.connections) do
list[#list+1]=i:sub(6,-1)
end
return list[math.random(1,#list)]
end
net.OnCastedClientInfo(function(client,name,ip,port)
multi.OnGUpdate(function(k,v)
@ -237,26 +277,30 @@ function multi:newMaster(name,settings) -- You will be able to have more than on
for i,v in pairs(master.connections) do
print(i)
end
client:send(char(CMD_INITMASTER)..name) -- Tell the node that you are a master trying to connect
client.OnDataRecieved(function(client,data)
local cmd = byte(data:sub(1,1)) -- the first byte is the command
local dat = data:sub(2,-1) -- the data that you want to read
if cmd == CMD_ERROR then
elseif cmd == CMD_PING then
elseif cmd == CMD_PONG then
elseif cmd == CMD_QUEUE then
local name,d=dat:match("(.-)|(.+)")
multi.OnNetQueue:Fire(name,d)
elseif cmd == CMD_GLOBAL then
local k,v = dat:match("(.-)|(.+)")
PROXY[k]=resolveData(v)
elseif cmd == CMD_LOAD then
local name,load = dat:match("(.-)|(.+)")
master.conn:Fire(name,tonumber(load))
end
client.OnClientReady(function()
client:send(char(CMD_INITMASTER)..name) -- Tell the node that you are a master trying to connect
client.OnDataRecieved(function(client,data)
local cmd = byte(data:sub(1,1)) -- the first byte is the command
local dat = data:sub(2,-1) -- the data that you want to read
master.trigger()
if cmd == CMD_ERROR then
elseif cmd == CMD_PING then
elseif cmd == CMD_PONG then
elseif cmd == CMD_QUEUE then
local name,d=dat:match("(.-)|(.+)")
multi.OnNetQueue:Fire(name,d)
elseif cmd == CMD_GLOBAL then
local k,v = dat:match("(.-)|(.+)")
PROXY[k]=resolveData(v)
print("Got Global Command")
elseif cmd == CMD_LOAD then
local name,load = dat:match("(.-)|(.+)")
master.loads[name]=tonumber(load)
end
end)
end)
end)
net:newCastedClients("NODE_(.+)") -- Searches for nodes and connects to them, the master.clients table will contain them by name
@ -265,5 +309,5 @@ end
-- The init function that gets returned
return {init = function()
return GLOBAL,THREAD
return GLOBAL
end}

View File

@ -1,8 +1,11 @@
package.path="?/init.lua;?.lua;"..package.path
multi = require("multi")
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
require("multi.integration.networkManager")
nGLOBAL = require("multi.integration.networkManager").init()
master = multi:newNode()
function RemoteTest()
print("Yes I work!")
end
settings = {
priority = 0, -- 1 or 2
protect = false,

View File

@ -1,11 +1,34 @@
-- set up the package
package.path="?/init.lua;?.lua;"..package.path
-- Import the libraries
multi = require("multi")
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
require("multi.integration.networkManager")
nGLOBAL = require("multi.integration.networkManager").init()
-- Run the code
master = multi:newMaster("Main")
-- Starting the multitasker
settings = {
priority = 0, -- 1 or 2
protect = false,
}
master.OnFirstNodeConnected(function()
print("Node connected lets go!")
master:newNetworkThread("Test_Thread",nil,function()
RemoteTest()
multi:newThread("test",function()
nGLOBAL["test"]="Did it work?"
end)
end)
multi:newThread("Checker",function()
while true do
thread.sleep(.5)
if nGLOBAL["test"] then
print(nGLOBAL["test"])
thread.kill()
end
end
end)
end)
os.execute("start lua node.lua")
multi:mainloop(settings)