GLOBAL table works
This commit is contained in:
parent
de2b3ee100
commit
644044901d
@ -44,6 +44,10 @@ multi.clock = os.clock
|
|||||||
multi.time = os.time
|
multi.time = os.time
|
||||||
multi.LinkedPath = multi
|
multi.LinkedPath = multi
|
||||||
multi.isRunning = false
|
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())
|
--Do not change these ever...Any other number will not work (Unless you are using enablePriority2())
|
||||||
multi.Priority_Core = 1
|
multi.Priority_Core = 1
|
||||||
multi.Priority_High = 4
|
multi.Priority_High = 4
|
||||||
@ -590,7 +594,7 @@ function multi:newConnection(protect)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
repeat
|
repeat
|
||||||
self.Parent:uManager()
|
self.Parent:uManager(multi.defaultSettings)
|
||||||
until self.waiting==false
|
until self.waiting==false
|
||||||
id:Destroy()
|
id:Destroy()
|
||||||
end
|
end
|
||||||
@ -747,6 +751,7 @@ function multi:newCondition(func)
|
|||||||
end
|
end
|
||||||
multi.NewCondition=multi.newCondition
|
multi.NewCondition=multi.newCondition
|
||||||
function multi:mainloop(settings)
|
function multi:mainloop(settings)
|
||||||
|
multi.defaultSettings = settings or multi.defaultSettings
|
||||||
if not multi.isRunning then
|
if not multi.isRunning then
|
||||||
local protect = false
|
local protect = false
|
||||||
local priority = false
|
local priority = false
|
||||||
@ -838,11 +843,12 @@ function multi:uManager(settings)
|
|||||||
settings.preLoop(self)
|
settings.preLoop(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
multi.defaultSettings = settings or multi.defaultSettings
|
||||||
self.uManager=self.uManagerRef
|
self.uManager=self.uManagerRef
|
||||||
end
|
end
|
||||||
function multi:uManagerRef(settings)
|
function multi:uManagerRef(settings)
|
||||||
if self.Active then
|
if self.Active then
|
||||||
if settings.priority==1 then
|
if multi.defaultSettings.priority==1 then
|
||||||
local Loop=self.Mainloop
|
local Loop=self.Mainloop
|
||||||
local PS=self
|
local PS=self
|
||||||
for _D=#Loop,1,-1 do
|
for _D=#Loop,1,-1 do
|
||||||
@ -851,7 +857,7 @@ function multi:uManagerRef(settings)
|
|||||||
if (PS.PList[P])%Loop[_D].Priority==0 then
|
if (PS.PList[P])%Loop[_D].Priority==0 then
|
||||||
if Loop[_D].Active then
|
if Loop[_D].Active then
|
||||||
self.CID=_D
|
self.CID=_D
|
||||||
if not settings.protect then
|
if not multi.defaultSettings.protect then
|
||||||
Loop[_D]:Act()
|
Loop[_D]:Act()
|
||||||
else
|
else
|
||||||
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
||||||
@ -865,7 +871,7 @@ function multi:uManagerRef(settings)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif settings.priority==2 then
|
elseif multi.defaultSettings.priority==2 then
|
||||||
local Loop=self.Mainloop
|
local Loop=self.Mainloop
|
||||||
local PS=self
|
local PS=self
|
||||||
for _D=#Loop,1,-1 do
|
for _D=#Loop,1,-1 do
|
||||||
@ -873,7 +879,7 @@ function multi:uManagerRef(settings)
|
|||||||
if (PS.PStep)%Loop[_D].Priority==0 then
|
if (PS.PStep)%Loop[_D].Priority==0 then
|
||||||
if Loop[_D].Active then
|
if Loop[_D].Active then
|
||||||
self.CID=_D
|
self.CID=_D
|
||||||
if not settings.protect then
|
if not multi.defaultSettings.protect then
|
||||||
Loop[_D]:Act()
|
Loop[_D]:Act()
|
||||||
else
|
else
|
||||||
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
||||||
@ -896,7 +902,7 @@ function multi:uManagerRef(settings)
|
|||||||
if Loop[_D] then
|
if Loop[_D] then
|
||||||
if Loop[_D].Active then
|
if Loop[_D].Active then
|
||||||
self.CID=_D
|
self.CID=_D
|
||||||
if not settings.protect then
|
if not multi.defaultSettings.protect then
|
||||||
Loop[_D]:Act()
|
Loop[_D]:Act()
|
||||||
else
|
else
|
||||||
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
local status, err=pcall(Loop[_D].Act,Loop[_D])
|
||||||
|
|||||||
@ -14,6 +14,7 @@ local CMD_INITNODE = 0x05
|
|||||||
local CMD_INITMASTER = 0x06
|
local CMD_INITMASTER = 0x06
|
||||||
local CMD_GLOBAL = 0x07
|
local CMD_GLOBAL = 0x07
|
||||||
local CMD_LOAD = 0x08
|
local CMD_LOAD = 0x08
|
||||||
|
local CMD_CALL = 0x09
|
||||||
|
|
||||||
local char = string.char
|
local char = string.char
|
||||||
local byte = string.byte
|
local byte = string.byte
|
||||||
@ -45,24 +46,10 @@ end
|
|||||||
function queue:peek()
|
function queue:peek()
|
||||||
return self[1]
|
return self[1]
|
||||||
end
|
end
|
||||||
|
local queues = {}
|
||||||
multi.OnNetQueue = multi:newConnection()
|
multi.OnNetQueue = multi:newConnection()
|
||||||
multi.OnGUpdate = 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
|
-- Managing the data that goes through the system
|
||||||
local function packData(data)
|
local function packData(data)
|
||||||
-- returns the data that was sterilized
|
-- returns the data that was sterilized
|
||||||
@ -104,6 +91,20 @@ local function resolveData(data)
|
|||||||
end
|
end
|
||||||
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
|
-- The main driving force of the network manager: Nodes
|
||||||
function multi:newNode(name,settings)
|
function multi:newNode(name,settings)
|
||||||
-- Here we have to use the net library to broadcast our node across the network
|
-- 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.server = net:newUDPServer(0) -- hosts the node using the default port
|
||||||
node.port = node.server.port
|
node.port = node.server.port
|
||||||
node.connections = net.ClientCache
|
node.connections = net.ClientCache
|
||||||
node.queue = newQueue()
|
node.queue = queue:newQueue()
|
||||||
|
node.loadRate=1
|
||||||
if settings then
|
if settings then
|
||||||
if settings.crossTalk then
|
if settings.crossTalk then
|
||||||
net.OnCastedClientInfo(function(client,name,ip,port)
|
net.OnCastedClientInfo(function(client,name,ip,port)
|
||||||
@ -157,30 +159,35 @@ function multi:newNode(name,settings)
|
|||||||
local name,d=dat:match("(.-)|(.+)")
|
local name,d=dat:match("(.-)|(.+)")
|
||||||
multi.OnNetQueue:Fire(name,d)
|
multi.OnNetQueue:Fire(name,d)
|
||||||
elseif cmd == CMD_TASK then
|
elseif cmd == CMD_TASK then
|
||||||
|
local args,func = dat:match("(.-)|(.+)")
|
||||||
|
func = resolveData(func)
|
||||||
|
args = resolveData(args)
|
||||||
|
func(unpack(args))
|
||||||
elseif cmd == CMD_INITNODE then
|
elseif cmd == CMD_INITNODE then
|
||||||
print("Connected with another node!")
|
print("Connected with another node!")
|
||||||
node.nodes[dat]={server,ip,port}
|
node.connections[dat]={server,ip,port}
|
||||||
multi.OnGUpdate(function(k,v)
|
multi.OnGUpdate(function(k,v)
|
||||||
server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port)
|
server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port)
|
||||||
end)
|
end)-- set this up
|
||||||
-- set this up
|
|
||||||
elseif cmd == CMD_INITMASTER then
|
elseif cmd == CMD_INITMASTER then
|
||||||
print("Connected to the master!")
|
print("Connected to the master!")
|
||||||
node.masters[dat]={server,ip,port}
|
node.connections[dat]={server,ip,port}
|
||||||
multi.OnGUpdate(function(k,v)
|
multi.OnGUpdate(function(k,v)
|
||||||
server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port)
|
server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port)
|
||||||
end)
|
end)-- set this up
|
||||||
-- 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
|
elseif cmd == CMD_GLOBAL then
|
||||||
local k,v = dat:match("(.-)|(.+)")
|
local k,v = dat:match("(.-)|(.+)")
|
||||||
PROXY[k]=resolveData(v)
|
PROXY[k]=resolveData(v)
|
||||||
elseif cmd == CMD_LOAD then
|
|
||||||
local load = multi:getLoad()
|
|
||||||
server:send(ip,node.name.."|"..load,port)
|
|
||||||
end
|
end
|
||||||
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)
|
self.connections[name]:send(data)
|
||||||
end
|
end
|
||||||
node.server:broadcast("NODE_"..name)
|
node.server:broadcast("NODE_"..name)
|
||||||
@ -188,46 +195,79 @@ function multi:newNode(name,settings)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Masters
|
-- 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 = {}
|
local master = {}
|
||||||
master.name = name
|
master.name = name
|
||||||
master.conn = multi:newConnection()
|
master.conn = multi:newConnection()
|
||||||
|
master.conn2 = multi:newConnection()
|
||||||
|
master.OnFirstNodeConnected = multi:newConnection()
|
||||||
master.queue = queue:newQueue()
|
master.queue = queue:newQueue()
|
||||||
master.connections = net.ClientCache -- Link to the client cache that is created on the net interface
|
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
|
master.loads = {}
|
||||||
local fData = CMD_TASK..packData(func)
|
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
|
if not name then
|
||||||
local name = self:getFreeNode()
|
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
|
else
|
||||||
local name = "NODE_"..name
|
local name = "NODE_"..name
|
||||||
self:sendTo(name,data)
|
self:sendTo(name,char(CMD_TASK)..aData..fData)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function master:sendTo(name,data)
|
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
|
end
|
||||||
function master:getFreeNode()
|
function master:getFreeNode()
|
||||||
local count = 0
|
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 min = math.huge
|
||||||
local ref
|
local refO
|
||||||
for i = 1,#list do
|
for i,v in pairs(master.loads) do
|
||||||
if list[i][1]<min then
|
if v<min then
|
||||||
min = list[i][1]
|
min = v
|
||||||
ref = list[i][2]
|
refO = i
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
net.OnCastedClientInfo(function(client,name,ip,port)
|
net.OnCastedClientInfo(function(client,name,ip,port)
|
||||||
multi.OnGUpdate(function(k,v)
|
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
|
for i,v in pairs(master.connections) do
|
||||||
print(i)
|
print(i)
|
||||||
end
|
end
|
||||||
client:send(char(CMD_INITMASTER)..name) -- Tell the node that you are a master trying to connect
|
client.OnClientReady(function()
|
||||||
client.OnDataRecieved(function(client,data)
|
client:send(char(CMD_INITMASTER)..name) -- Tell the node that you are a master trying to connect
|
||||||
local cmd = byte(data:sub(1,1)) -- the first byte is the command
|
client.OnDataRecieved(function(client,data)
|
||||||
local dat = data:sub(2,-1) -- the data that you want to read
|
local cmd = byte(data:sub(1,1)) -- the first byte is the command
|
||||||
if cmd == CMD_ERROR then
|
local dat = data:sub(2,-1) -- the data that you want to read
|
||||||
|
master.trigger()
|
||||||
elseif cmd == CMD_PING then
|
if cmd == CMD_ERROR then
|
||||||
|
|
||||||
elseif cmd == CMD_PONG then
|
elseif cmd == CMD_PING then
|
||||||
|
|
||||||
elseif cmd == CMD_QUEUE then
|
elseif cmd == CMD_PONG then
|
||||||
local name,d=dat:match("(.-)|(.+)")
|
|
||||||
multi.OnNetQueue:Fire(name,d)
|
elseif cmd == CMD_QUEUE then
|
||||||
elseif cmd == CMD_GLOBAL then
|
local name,d=dat:match("(.-)|(.+)")
|
||||||
local k,v = dat:match("(.-)|(.+)")
|
multi.OnNetQueue:Fire(name,d)
|
||||||
PROXY[k]=resolveData(v)
|
elseif cmd == CMD_GLOBAL then
|
||||||
elseif cmd == CMD_LOAD then
|
local k,v = dat:match("(.-)|(.+)")
|
||||||
local name,load = dat:match("(.-)|(.+)")
|
PROXY[k]=resolveData(v)
|
||||||
master.conn:Fire(name,tonumber(load))
|
print("Got Global Command")
|
||||||
end
|
elseif cmd == CMD_LOAD then
|
||||||
|
local name,load = dat:match("(.-)|(.+)")
|
||||||
|
master.loads[name]=tonumber(load)
|
||||||
|
end
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
net:newCastedClients("NODE_(.+)") -- Searches for nodes and connects to them, the master.clients table will contain them by name
|
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
|
-- The init function that gets returned
|
||||||
return {init = function()
|
return {init = function()
|
||||||
return GLOBAL,THREAD
|
return GLOBAL
|
||||||
end}
|
end}
|
||||||
5
node.lua
5
node.lua
@ -1,8 +1,11 @@
|
|||||||
package.path="?/init.lua;?.lua;"..package.path
|
package.path="?/init.lua;?.lua;"..package.path
|
||||||
multi = require("multi")
|
multi = require("multi")
|
||||||
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
||||||
require("multi.integration.networkManager")
|
nGLOBAL = require("multi.integration.networkManager").init()
|
||||||
master = multi:newNode()
|
master = multi:newNode()
|
||||||
|
function RemoteTest()
|
||||||
|
print("Yes I work!")
|
||||||
|
end
|
||||||
settings = {
|
settings = {
|
||||||
priority = 0, -- 1 or 2
|
priority = 0, -- 1 or 2
|
||||||
protect = false,
|
protect = false,
|
||||||
|
|||||||
25
test.lua
25
test.lua
@ -1,11 +1,34 @@
|
|||||||
|
-- set up the package
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
package.path="?/init.lua;?.lua;"..package.path
|
||||||
|
-- Import the libraries
|
||||||
multi = require("multi")
|
multi = require("multi")
|
||||||
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
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")
|
master = multi:newMaster("Main")
|
||||||
|
-- Starting the multitasker
|
||||||
settings = {
|
settings = {
|
||||||
priority = 0, -- 1 or 2
|
priority = 0, -- 1 or 2
|
||||||
protect = false,
|
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)
|
multi:mainloop(settings)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user