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.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])
|
||||
|
||||
@ -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)
|
||||
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,10 +277,12 @@ 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.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
|
||||
@ -253,17 +295,19 @@ function multi:newMaster(name,settings) -- You will be able to have more than on
|
||||
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.conn:Fire(name,tonumber(load))
|
||||
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
|
||||
return master
|
||||
end
|
||||
|
||||
-- The init function that gets returned
|
||||
return {init = function()
|
||||
return GLOBAL,THREAD
|
||||
return GLOBAL
|
||||
end}
|
||||
5
node.lua
5
node.lua
@ -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,
|
||||
|
||||
25
test.lua
25
test.lua
@ -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)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user