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