Download CommonLua/BufferedProcess.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 10.1 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/BufferedProcess.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/BufferedProcess.lua
-
curl -L -o BufferedProcess.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/BufferedProcess.lua
10.1 kB
| --- Holds a flag indicating whether there are any pending reasons to suspend the process. | |
| --- Holds a flag indicating whether there are any pending reasons to suspend the process. | |
| --- | |
| --- @type boolean | |
| SuspendProcessReasons = nil | |
| --- Holds a flag indicating whether the process is currently suspended. | |
| --- | |
| --- @type boolean | |
| SuspendedProcessing = nil | |
| --- A function that checks the current execution timestamp. | |
| --- | |
| --- @type function | |
| CheckExecutionTimestamp = empty_func | |
| --- A function that checks for any remaining reasons to suspend the process. | |
| --- | |
| --- @type function | |
| CheckRemainingReason = empty_func | |
| --- A function that unpacks a table. | |
| --- | |
| --- @type function | |
| table_unpack = table.unpack | |
| --- A function that checks if two tables are equal. | |
| --- | |
| --- @type function | |
| table_iequal = table.iequal | |
| local SuspendProcessReasons | |
| local SuspendedProcessing | |
| local CheckExecutionTimestamp = empty_func | |
| local CheckRemainingReason = empty_func | |
| local table_unpack = table.unpack | |
| local table_iequal = table.iequal | |
| if FirstLoad then | |
| __process_params_meta = { | |
| __eq = function(t1, t2) | |
| if type(t1) ~= type(t2) or not rawequal(getmetatable(t1), getmetatable(t2)) then | |
| return false | |
| end | |
| local count = t1[1] | |
| if count ~= t2[1] then | |
| return false | |
| end | |
| for i=2,count do | |
| if t1[i] ~= t2[i] then | |
| return false | |
| end | |
| end | |
| return true | |
| end | |
| } | |
| end | |
| --- | |
| --- Packs the provided parameters into a table with a metatable that allows for efficient equality comparison. | |
| --- | |
| --- @param obj any The first parameter to be packed. | |
| --- @param ... any Additional parameters to be packed. | |
| --- @return table A table containing the packed parameters, with a metatable that allows for efficient equality comparison. | |
| --- | |
| local function PackProcessParams(obj, ...) | |
| local count = select("#", ...) | |
| if count == 0 then | |
| return obj or false | |
| end | |
| return setmetatable({count + 2, obj, ...}, __process_params_meta) | |
| end | |
| --- | |
| --- Unpacks the parameters from a table that was packed using the `PackProcessParams` function. | |
| --- | |
| --- @param params table A table containing the packed parameters, with a metatable that allows for efficient equality comparison. | |
| --- @return any The unpacked parameters. | |
| --- | |
| function UnpackProcessParams(params) | |
| if type(params) ~= "table" or getmetatable(params) ~= __process_params_meta then | |
| return params | |
| end | |
| return table_unpack(params, 2, params[1]) | |
| end | |
| function OnMsg.DoneMap() | |
| CheckRemainingReason() | |
| SuspendProcessReasons = false | |
| SuspendedProcessing = false | |
| end | |
| --- | |
| --- Executes any suspended functions for the given process. | |
| --- | |
| --- @param process string The name of the process for which to execute suspended functions. | |
| --- | |
| function ExecuteSuspended(process) | |
| -- Implementation details omitted for brevity | |
| end | |
| local function ExecuteSuspended(process) | |
| local delayed = SuspendedProcessing | |
| local funcs_to_params = delayed and delayed[process] | |
| if not funcs_to_params then | |
| return | |
| end | |
| delayed[process] = nil | |
| local procall = procall | |
| for _, funcname in ipairs(funcs_to_params) do | |
| local func = _G[funcname] | |
| for _, params in ipairs(funcs_to_params[funcname]) do | |
| dbg(CheckExecutionTimestamp(process, funcname, params, true)) | |
| procall(func, UnpackProcessParams(params)) | |
| end | |
| end | |
| end | |
| --- | |
| --- Cancels the processing of routines from a named process. | |
| --- | |
| --- @param process string The name of the process for which to cancel processing. | |
| --- | |
| function CancelProcessing(process) | |
| if not SuspendProcessReasons or not SuspendProcessReasons[process] then | |
| return | |
| end | |
| if SuspendedProcessing then | |
| SuspendedProcessing[process] = nil | |
| end | |
| SuspendProcessReasons[process] = nil | |
| Msg("ProcessingResumed", process, "cancel") | |
| end | |
| --[[@@@ | |
| Checks if the processing of routines from a named process is currently suspended | |
| @function bool IsProcessingSuspended(string process) | |
| --]] | |
| function IsProcessingSuspended(process) | |
| local process_to_reasons = SuspendProcessReasons | |
| return process_to_reasons and next(process_to_reasons[process]) | |
| end | |
| --[[@@@ | |
| Suspends the processing of routines from a named process. Multiple suspending with the same reason would lead to an error. | |
| @function void SuspendProcessing(string process, type reason, bool ignore_errors) | |
| @param string process - the name of the process, which routines should be suspended. | |
| @param type reason - the reason to be used in order to resume the processing later. Could be any type. | |
| @param bool ignore_errors - ignore suspending errors (e.g. process already suspended). | |
| --]] | |
| function SuspendProcessing(process, reason, ignore_errors) | |
| reason = reason or "" | |
| local reasons = SuspendProcessReasons and SuspendProcessReasons[process] | |
| if reasons and reasons[reason] then | |
| assert(ignore_errors) | |
| return | |
| end | |
| local now = GameTime() | |
| if reasons then | |
| reasons[reason] = now | |
| return | |
| end | |
| SuspendProcessReasons = table.set(SuspendProcessReasons, process, reason, now) | |
| Msg("ProcessingSuspended", process) | |
| end | |
| --[[@@@ | |
| Resumes the processing of routines from a named process. Resuming an already resumed process, or resuming it with time delay, would lead to an error. | |
| @function void ResumeProcessing(string process, type reason, bool ignore_errors) | |
| @param string process - the name of the process, which routines should be suspended. | |
| @param type reason - the reason to be used in order to resume the processing later. Could be any type. | |
| @param bool ignore_errors - ignore resume errors (e.g. process already resumed). | |
| --]] | |
| function ResumeProcessing(process, reason, ignore_errors) | |
| reason = reason or "" | |
| local reasons = SuspendProcessReasons and SuspendProcessReasons[process] | |
| local suspended = reasons and reasons[reason] | |
| if not suspended then | |
| return | |
| end | |
| assert(ignore_errors or suspended == GameTime()) | |
| local now = GameTime() | |
| reasons[reason] = nil | |
| if next(reasons) ~= nil then | |
| return | |
| end | |
| assert(not IsProcessingSuspended(process)) | |
| ExecuteSuspended(process) | |
| Msg("ProcessingResumed", process) | |
| end | |
| --[[@@@ | |
| Execute a routine from a named process. If the process is currently suspended, the call will be registered in ordered to be executed once the process is resumed. Multiple calls with the same context will be registered as one. | |
| @function void ExecuteProcess(string process, function func, table obj) | |
| @param string process - the name of the process, which routines should be suspended. | |
| @param function func - the function to be executed. | |
| @param table obj - optional function context. | |
| --]] | |
| function ExecuteProcess(process, funcname, obj, ...) | |
| if not IsProcessingSuspended(process) then | |
| dbg(CheckExecutionTimestamp(process, funcname, obj)) | |
| return procall(_G[funcname], obj, ...) | |
| end | |
| local params = PackProcessParams(obj, ...) | |
| local suspended = SuspendedProcessing | |
| if not suspended then | |
| suspended = {} | |
| SuspendedProcessing = suspended | |
| end | |
| local funcs_to_params = suspended[process] | |
| if not funcs_to_params then | |
| suspended[process] = { funcname, [funcname] = {params} } | |
| return | |
| end | |
| local objs = funcs_to_params[funcname] | |
| if not objs then | |
| funcs_to_params[#funcs_to_params + 1] = funcname | |
| funcs_to_params[funcname] = {params} | |
| return | |
| end | |
| table.insert_unique(objs, params) | |
| end | |
| ---- | |
| if Platform.asserts then | |
| local ExecutionTimestamps | |
| function OnMsg.DoneMap() | |
| ExecutionTimestamps = false | |
| end | |
| -- Rise an error if a routine from a process is executed twice in the same time | |
| --[[@@@ | |
| Checks if a process routine has been executed more than once in the same time frame. | |
| @function void CheckExecutionTimestamp(string process, string funcname, table obj, boolean delayed) | |
| @param string process - the name of the process | |
| @param string funcname - the name of the function being executed | |
| @param table obj - the object context of the function being executed | |
| @param boolean delayed - whether the function call is delayed | |
| @return boolean - true if the function has been executed more than once, false otherwise | |
| --]] | |
| CheckExecutionTimestamp = function(process, funcname, obj, delayed) | |
| if not config.DebugSuspendProcess then | |
| return | |
| end | |
| if not ExecutionTimestamps then | |
| ExecutionTimestamps = {} | |
| CreateRealTimeThread(function() | |
| Sleep(1) | |
| ExecutionTimestamps = false | |
| end) | |
| end | |
| local func_to_objs = ExecutionTimestamps[process] | |
| if not func_to_objs then | |
| func_to_objs = {} | |
| ExecutionTimestamps[process] = func_to_objs | |
| end | |
| local objs_to_timestamp = func_to_objs[funcname] | |
| if not objs_to_timestamp then | |
| objs_to_timestamp = {} | |
| func_to_objs[funcname] = objs_to_timestamp | |
| end | |
| obj = obj or false | |
| local rtime, gtime = RealTime(), GameTime() | |
| local timestamp = xxhash(rtime, gtime) | |
| if timestamp == objs_to_timestamp[obj] then | |
| print("Duplicated processing:", process, funcname, "time:", gtime, "obj:", obj and obj.class, | |
| obj and obj.handle) | |
| assert(false, string.format("Duplicated process routine: %s.%s", process, funcname)) | |
| else | |
| objs_to_timestamp[obj] = timestamp | |
| --[[ | |
| if IsValid(obj) then | |
| local pos = obj:GetVisualPos() | |
| local seed = xxhash(obj and obj.handle) | |
| local len = 5*guim + BraidRandom(seed, 10*guim) | |
| DbgAddVector(pos, len, RandColor(seed)) | |
| DbgAddText(funcname, pos + point(0, 0, len), RandColor(obj and obj.handle)) | |
| end | |
| --]] | |
| end | |
| end | |
| --- | |
| --- Checks if there are any remaining reasons for suspending a process. | |
| --- If there are any remaining reasons, an assertion is triggered with the process name and reason. | |
| --- | |
| --- @function CheckRemainingReason | |
| --- @return nil | |
| CheckRemainingReason = function() | |
| local process = next(SuspendProcessReasons) | |
| local reason = process and next(SuspendProcessReasons[process]) | |
| if reason then | |
| assert(false, string.format("Process '%s' not resumed: %s", process, ValueToStr(reason))) | |
| end | |
| end | |
| end -- Platform.asserts |