#110 periodically call unserviced TCD callbacks

This commit is contained in:
Mikayla Fischler 2022-10-23 12:21:17 -04:00
parent 307bf6e2c8
commit a02fb6f691
4 changed files with 47 additions and 8 deletions

View File

@ -16,7 +16,7 @@ local config = require("coordinator.config")
local coordinator = require("coordinator.coordinator") local coordinator = require("coordinator.coordinator")
local renderer = require("coordinator.renderer") local renderer = require("coordinator.renderer")
local COORDINATOR_VERSION = "alpha-v0.5.7" local COORDINATOR_VERSION = "alpha-v0.5.9"
local print = util.print local print = util.print
local println = util.println local println = util.println
@ -181,8 +181,7 @@ if ui_ok then
log_sys("system started successfully") log_sys("system started successfully")
end end
-- event loop -- main event loop
-- ui_ok will never change in this loop, same as while true or exit if UI start failed
while ui_ok do while ui_ok do
local event, param1, param2, param3, param4, param5 = util.pull_event() local event, param1, param2, param3, param4, param5 = util.pull_event()
@ -299,6 +298,9 @@ while ui_ok do
renderer.handle_touch(core.events.touch(param1, param2, param3)) renderer.handle_touch(core.events.touch(param1, param2, param3))
end end
-- call unserviced TCD callbacks
tcallbackdsp.call_unserviced()
-- check for termination request -- check for termination request
if event == "terminate" or ppm.should_terminate() then if event == "terminate" or ppm.should_terminate() then
println_ts("terminate requested, closing connections...") println_ts("terminate requested, closing connections...")

View File

@ -9,6 +9,8 @@ local tcallbackdsp = {}
local registry = {} local registry = {}
local UNSERVICED_CALL_DELAY = util.TICK_TIME_S
-- request a function to be called after the specified time -- request a function to be called after the specified time
---@param time number seconds ---@param time number seconds
---@param f function callback function ---@param f function callback function
@ -20,7 +22,7 @@ function tcallbackdsp.dispatch(time, f)
expiry = time + util.time_s() expiry = time + util.time_s()
} }
log.debug("queued callback for " .. util.strval(f) .. " timer #" .. timer) -- log.debug(util.c("TCD: queued callback for ", f, " [timer: ", timer, "]"))
end end
-- request a function to be called after the specified time, aborting any registered instances of that function reference -- request a function to be called after the specified time, aborting any registered instances of that function reference
@ -31,7 +33,7 @@ function tcallbackdsp.dispatch_unique(time, f)
for timer, entry in pairs(registry) do for timer, entry in pairs(registry) do
if entry.callback == f then if entry.callback == f then
-- found an instance of this function reference, abort it -- found an instance of this function reference, abort it
log.debug(util.c("TCD: aborting duplicate timer callback (timer: ", timer, ", ", f, ")")) log.debug(util.c("TCD: aborting duplicate timer callback [timer: ", timer, ", ", f, "]"))
-- cancel event and remove from registry (even if it fires it won't call) -- cancel event and remove from registry (even if it fires it won't call)
util.cancel_timer(timer) util.cancel_timer(timer)
@ -46,7 +48,7 @@ function tcallbackdsp.dispatch_unique(time, f)
expiry = time + util.time_s() expiry = time + util.time_s()
} }
log.debug("queued callback for " .. util.strval(f) .. " timer #" .. timer) -- log.debug(util.c("TCD: queued callback for ", f, " [timer: ", timer, "]"))
end end
-- lookup a timer event and execute the callback if found -- lookup a timer event and execute the callback if found
@ -60,14 +62,44 @@ function tcallbackdsp.handle(event)
end end
end end
-- execute any callbacks that are overdo their time and have not been serviced
--
-- this can be called periodically to prevent loss of any callbacks do to timer events that are lost (see github issue #110)
function tcallbackdsp.call_unserviced()
local found_unserviced = true
while found_unserviced do
found_unserviced = false
-- go through registry, restart if unserviced entries were found due to mutating registry table
for timer, entry in pairs(registry) do
found_unserviced = util.time_s() > (entry.expiry + UNSERVICED_CALL_DELAY)
if found_unserviced then
local overtime = util.time_s() - entry.expiry
local callback = entry.callback
log.warning(util.c("TCD: executing unserviced callback ", entry.callback, " (", overtime, "s late) [timer: ", timer, "]"))
-- clear first so that dispatch_unique call from inside callback won't see it as a conflict
registry[timer] = nil
callback()
break
end
end
end
end
-- identify any overdo callbacks -- identify any overdo callbacks
-- --
-- prints to log debug output -- prints to log debug output
function tcallbackdsp.diagnostics() function tcallbackdsp.diagnostics()
for timer, entry in pairs(registry) do for timer, entry in pairs(registry) do
if entry.expiry >= util.time_s() then if entry.expiry < util.time_s() then
local overtime = util.time_s() - entry.expiry local overtime = util.time_s() - entry.expiry
log.debug(util.c("TCD: unserviced timer ", timer, " for callback ", entry.callback, " is at least ", overtime, "s late")) log.debug(util.c("TCD: unserviced timer ", timer, " for callback ", entry.callback, " is at least ", overtime, "s late"))
else
local time = entry.expiry - util.time_s()
log.debug(util.c("TCD: pending timer ", timer, " for callback ", entry.callback, " (call after ", entry.duration, "s, expires ", time, ")"))
end end
end end
end end

View File

@ -5,6 +5,11 @@
---@class util ---@class util
local util = {} local util = {}
-- ENVIRONMENT CONSTANTS --
util.TICK_TIME_S = 0.05
util.TICK_TIME_MS = 50
-- OPERATORS -- -- OPERATORS --
-- trinary operator -- trinary operator