Create Event.lua

This commit is contained in:
IgorTimofeev 2022-05-06 19:52:53 +03:00 committed by GitHub
parent 2b68b4b4f9
commit 8f5e89a645
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,134 +1,138 @@
local event, handlers, interruptingKeysDown, lastInterrupt = { local event, handlers, interruptingKeysDown, lastInterrupt = {
interruptingEnabled = true, interruptingEnabled = true,
interruptingDelay = 1, interruptingDelay = 1,
interruptingFunction = error, defaultInterruptingFunction = function()
defaultInterruptingFunction = error, error("interrupted", 0)
interruptingKeyCodes = { end,
[29] = true, interruptingKeyCodes = {
[46] = true, [29] = true,
[56] = true [46] = true,
}, [56] = true
push = computer.pushSignal },
push = computer.pushSignal
}, {}, {}, 0 }, {}, {}, 0
event.interruptingFunction = event.defaultInterruptingDFunction
local computerPullSignal, computerUptime, mathHuge, mathMin, skipSignalType = computer.pullSignal, computer.uptime, math.huge, math.min local computerPullSignal, computerUptime, mathHuge, mathMin, skipSignalType = computer.pullSignal, computer.uptime, math.huge, math.min
-------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------
function event.addHandler(callback, interval, times) function event.addHandler(callback, interval, times)
checkArg(1, callback, "function") checkArg(1, callback, "function")
checkArg(2, interval, "number", "nil") checkArg(2, interval, "number", "nil")
checkArg(3, times, "number", "nil") checkArg(3, times, "number", "nil")
local handler = { local handler = {
callback = callback, callback = callback,
times = times or mathHuge, times = times or mathHuge,
interval = interval, interval = interval,
nextTriggerTime = interval and computerUptime() + interval or 0 nextTriggerTime = interval and computerUptime() + interval or 0
} }
handlers[handler] = true handlers[handler] = true
return handler return handler
end end
function event.removeHandler(handler) function event.removeHandler(handler)
checkArg(1, handler, "table") checkArg(1, handler, "table")
if handlers[handler] then if handlers[handler] then
handlers[handler] = nil handlers[handler] = nil
return true return true
else else
return false, "Handler with given table is not registered" return false, "Handler with given table is not registered"
end end
end end
function event.getHandlers() function event.getHandlers()
return handlers return handlers
end end
function event.skip(signalType) function event.skip(signalType)
skipSignalType = signalType skipSignalType = signalType
end end
function event.pull(preferredTimeout) function event.pull(preferredTimeout)
local uptime, signalData = computerUptime() local uptime, signalData = computerUptime()
local deadline = uptime + (preferredTimeout or mathHuge) local deadline = uptime + (preferredTimeout or mathHuge)
repeat repeat
-- Determining pullSignal timeout -- Determining pullSignal timeout
timeout = deadline timeout = deadline
for handler in pairs(handlers) do for handler in pairs(handlers) do
if handler.nextTriggerTime > 0 then if handler.nextTriggerTime > 0 then
timeout = mathMin(timeout, handler.nextTriggerTime) timeout = mathMin(timeout, handler.nextTriggerTime)
end end
end end
-- Pulling signal data -- Pulling signal data
signalData = { computerPullSignal(timeout - computerUptime()) } signalData = { computerPullSignal(timeout - computerUptime()) }
-- Handlers processing -- Handlers processing
for handler in pairs(handlers) do for handler in pairs(handlers) do
if handler.times > 0 then if handler.times > 0 then
uptime = computerUptime() uptime = computerUptime()
if if
handler.nextTriggerTime <= uptime handler.nextTriggerTime <= uptime
then then
handler.times = handler.times - 1 handler.times = handler.times - 1
if handler.nextTriggerTime > 0 then if handler.nextTriggerTime > 0 then
handler.nextTriggerTime = uptime + handler.interval handler.nextTriggerTime = uptime + handler.interval
end end
-- Callback running -- Callback running
handler.callback(table.unpack(signalData)) handler.callback(table.unpack(signalData))
end end
else else
handlers[handler] = nil handlers[handler] = nil
end end
end end
-- Program interruption support. It's faster to do it here instead of registering handlers -- Program interruption support. It's faster to do it here instead of registering handlers
if (signalData[1] == "key_down" or signalData[1] == "key_up") and event.interruptingEnabled then if (signalData[1] == "key_down" or signalData[1] == "key_up") and event.interruptingEnabled then
-- Analysing for which interrupting key is pressed - we don't need keyboard API for this -- Analysing for which interrupting key is pressed - we don't need keyboard API for this
if event.interruptingKeyCodes[signalData[4]] then if event.interruptingKeyCodes[signalData[4]] then
interruptingKeysDown[signalData[4]] = signalData[1] == "key_down" and true or nil interruptingKeysDown[signalData[4]] = signalData[1] == "key_down" and true or nil
end end
local shouldInterrupt = true local shouldInterrupt = true
for keyCode in pairs(event.interruptingKeyCodes) do for keyCode in pairs(event.interruptingKeyCodes) do
if not interruptingKeysDown[keyCode] then if not interruptingKeysDown[keyCode] then
shouldInterrupt = false shouldInterrupt = false
end end
end end
if shouldInterrupt and uptime - lastInterrupt > event.interruptingDelay then if shouldInterrupt and uptime - lastInterrupt > event.interruptingDelay then
lastInterrupt = uptime lastInterrupt = uptime
event.interruptingFunction("interrupted", 0)
end event.interruptingFunction()
end end
end
-- Loop-breaking condition
if signalData[1] then -- Loop-breaking condition
if signalData[1] == skipSignalType then if signalData[1] then
skipSignalType = nil if signalData[1] == skipSignalType then
else skipSignalType = nil
return table.unpack(signalData) else
end return table.unpack(signalData)
end end
until uptime >= deadline end
until uptime >= deadline
end end
-- Sleeps "time" of seconds via "busy-wait" concept -- Sleeps "time" of seconds via "busy-wait" concept
function event.sleep(time) function event.sleep(time)
checkArg(1, time, "number", "nil") checkArg(1, time, "number", "nil")
local deadline = computerUptime() + (time or 0) local deadline = computerUptime() + (time or 0)
repeat repeat
event.pull(deadline - computerUptime()) event.pull(deadline - computerUptime())
until computerUptime() >= deadline until computerUptime() >= deadline
end end
-------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------