Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Threads
- --[[
- Documenation:
- This script will allow you to easily execute any non-Phasor function in Lua lanes.
- Lanes allow you to execute multiple chunks of code at once, which will ultimately solve all lag issues with functions that require a lot of power.
- In order for this to work, you MUST specify all functions and global variables lanes will be using in the 'global' table (see below).
- There are only a few functions and they are all specifically made to be straightforward and easier to use than lanes by itself.
- The examples given in each of the function descriptions will build a script that will request a player's stats from a website and write to them in the script.
- thread.execute(func, ...)
- -- func: <string> The name of the function you want to be executed in a separate thread.
- -- ...: <any amount of data> The parameters that should be passed into the function you're calling in a separate thread.
- Returns: Key which will be used for retrieving returned data.
- Example:
- global = {"getstats"}
- URL = "http://www.phasorstats.com/examplestats" -- not a real URL; just used for the sake of example
- function OnPlayerJoin(player)
- local hash = gethash(player)
- local key = thread.execute("getstats", hash)
- end
- function getstats(hash)
- local http = require "socket.http"
- local info = http.request(URL .. "/" .. hash) -- pretending that the stats are stored at "http://www.phasorstats.com/examplestats/" .. hash
- return assert(load(info))() -- assuming the data is sent from the website in the same form as table.save saves tables
- end
- Notes:
- -- Make sure all functions you use in thread.execute are in the global table, including functions called within the functions you use in thread.execute.
- -- Once again, Phasor functions DO NOT WORK in separate threads, so make sure the function you are passing has no Phasor functions.
- thread.receive(key)
- -- key: <string> Key returned by thread.execute to access the return value of the function call.
- Returns: What is returned by the function passed into thread.execute at the specified key.
- Example:
- global = {"http", "getstats"}
- URL = "http://www.phasorstats.com/examplestats" -- not a real URL; just used for the sake of example
- function OnPlayerJoin(player)
- local hash = gethash(player)
- local key = thread.execute("getstats", hash)
- registertimer(100, "ReceiveStats", {player, key}) -- we need to register a timer that will check to see when the thread finishes executing and has a response.
- end
- function ReceiveStats(id, count, info)
- local player, key = table.unpack(info)
- if thread.done(key) then -- thread.done example (see thread.done syntax for info)
- local hash = gethash(player)
- stats[hash] = thread.receive(key) -- set the player's stats to what getstats returns
- return false -- no need to keep this timer running
- end
- return true -- keep calling the timer until getstats is finished executing
- end
- function getstats(hash)
- local http = require "socket.http"
- local info = http.request(URL .. "/" .. hash) -- pretending that the stats are stored at "http://www.phasorstats.com/examplestats/" .. hash
- return assert(load(info))() -- assuming the data is sent from the website in the same form as table.save saves tables
- end
- thread.done(key)
- -- key: <string> Key returned by thread.execute.
- Returns: Boolean specifying if the thread has finished (true or false).
- Example:
- (See example for thread.receive)
- thread.cancel(key)
- -- key: <string> Key returned by thread.execute.
- Example:
- statsthread = {}
- global = {"http", "getstats"}
- URL = "http://www.phasorstats.com/examplestats" -- not a real URL; just used for the sake of example
- function OnPlayerJoin(player)
- local hash = gethash(player)
- local key = thread.execute("getstats", hash)
- statsthread[player] = key
- registertimer(100, "ReceiveStats", {player, key}) -- we need to register a timer that will check to see when the thread finishes executing and has a response.
- end
- function OnPlayerLeave(player)
- thread.cancel(statsthread[player])
- end
- function ReceiveStats(id, count, info)
- local player, key = table.unpack(info)
- if thread.done(key) then -- thread.done example (see thread.done syntax for info)
- local hash = gethash(player)
- stats[hash] = thread.receive(key) -- set the player's stats to what getstats returns
- return false -- no need to keep this timer running
- end
- return true -- keep calling the timer until getstats is finished executing
- end
- function getstats(hash)
- local http = require "socket.http"
- local info = http.request(URL .. "/" .. hash) -- pretending that the stats are stored at "http://www.phasorstats.com/examplestats/" .. hash
- return assert(load(info))() -- assuming the data is sent from the website in the same form as table.save saves tables
- end
- Notes:
- -- This is only necessary if you want to stop a thread from attempting to execute a function.
- -- In the case of our stats example, we want to cancel the thread from executing if the player leaves before we can access his/her stats.
- -- Using thread.cancel on a key that has already finished executing has no effect.
- Miscellaneous Notes:
- -- Make sure functions you execute in separate threads don't have random number calculations in them; they will probably always end up being the same.
- -- If you are using other libraries (like socket), make sure you require them in the function they're being used in (see thread.execute example).
- If you have any questions about this script, PM me (Nuggets) at phasor.proboards.com.
- --]]
- -- The Global Table --
- -- Insert the names of user-created (i.e. not string.gsub, table.len, etc.) variables as strings which will be used in lanes, including functions used in functions you specify.
- -- For example, if your function called "somefunction" uses a function within it called "anotherfunction", you must also include "anotherfunction" for "somefunction" to work.
- -- You may not use Phasor functions (you will get a Lua Lanes error).
- global = {}
- -- Don't edit below this line --
- local lanes = require "lanes"
- lanes.configure()
- local linda = lanes.linda()
- lua_lanes_error = false
- thread = {}
- function GetRequiredVersion()
- return 200
- end
- function OnScriptLoad(processId, game, persistent)
- laneglobals = GetGlobalTable()
- workerhandle = lanes.gen("*", {globals = laneglobals}, Worker)
- registertimer(100, "ErrorCheck")
- registertimer(10, "Sender")
- registertimer(10, "Receiver")
- end
- function GetGlobalTable()
- funcs = {}
- for _,func in ipairs(global) do
- local split = string.split(func, ".")
- local f = "funcs"
- local g = "_G"
- for k,v in ipairs(split) do
- if type(v) == "string" then
- v = "\"" .. v .. "\""
- end
- f = f .. "[" .. v .. "]"
- g = g .. "[" .. v .. "]"
- assert(load(f .. " = " .. f .. " or " .. g .. " or {}"))()
- end
- assert(load(f .. " = " .. g))()
- end
- return funcs
- end
- function Worker(key)
- while true do
- local _,cmd = linda:receive("command: " .. key)
- local _,parameters = linda:receive("parameters: " .. key)
- if cmd == "thread.cancel" then
- linda:send("returnthread.cancel" .. key)
- break
- else
- if _G[cmd] then
- local v = {_G[cmd](table.unpack(parameters))}
- linda:send("return " .. key, v)
- else
- print("Warning: " .. cmd .. " not defined in global table!")
- print("Execution of " .. cmd .. " has been cancelled.")
- end
- break
- end
- end
- end
- function Sender(id, count)
- for k,v in pairs(thread) do
- if type(v) == "table" then
- if not thread[k].sent then
- thread[k].sent = true
- thread[k].handle = workerhandle(k)
- end
- end
- end
- return not lua_lanes_error
- end
- function Receiver(id, count)
- for k,v in pairs(thread) do
- if type(v) == "table" then
- if not thread[k].done then
- _,thread[k].value = linda:receive(0, "return " .. k)
- if thread[k].value then
- thread[k].done = true
- thread[k].handle = nil
- end
- end
- end
- end
- return not lua_lanes_error
- end
- function ErrorCheck(id, count)
- for k,v in pairs(thread) do
- if type(v) == "table" then
- local worker = thread[k].handle
- if worker then
- if worker.status == "error" then
- hprintf("Lua Lanes Error:")
- _, err = worker:join()
- hprintf(err)
- lua_lanes_error = true
- return false
- end
- end
- end
- end
- return true
- end
- function thread.execute(func, ...)
- local args = {...}
- for k,v in ipairs(args) do
- args[k] = tostring(v)
- end
- local key = func .. table.concat(args, "")
- if not thread[key] then
- linda:send("command: " .. key, func)
- linda:send("parameters: " .. key, {...})
- thread[key] = {}
- end
- return key
- end
- function thread.receive(key)
- return table.unpack(thread[key].value)
- end
- function thread.done(key)
- return thread[key].done or false
- end
- function thread.cancel(key)
- thread.execute("thread.cancel", key)
- local worker = thread[key].handle
- if worker then
- while worker.status == "running" or worker.status == "waiting" do end
- end
- end
- function string.split(str, ...)
- local args = {...}
- for k,v in ipairs(args) do
- if v == "" then
- local subs = {}
- for i = 1,string.len(str) do
- table.insert(subs, string.sub(str, i, i))
- end
- return subs
- end
- end
- local subs = {}
- local sub = ""
- for i = 1,string.len(str) do
- local bool
- local char = string.sub(str, i, i)
- for k,v in ipairs(args) do
- local delim = string.sub(str, i - (string.len(v) - 1), i)
- if v == delim then
- bool = true
- sub = string.sub(sub, 1, string.len(sub) - (string.len(v) - 1))
- if sub ~= "" then
- table.insert(subs, sub)
- end
- sub = ""
- break
- end
- end
- if not bool then
- sub = sub .. char
- end
- if i == string.len(str) then
- table.insert(subs, sub)
- end
- end
- return subs
- end
Advertisement
Add Comment
Please, Sign In to add comment