diff --git a/Libraries/Event.lua b/Libraries/Event.lua index 6bfe2148..b067e1ef 100755 --- a/Libraries/Event.lua +++ b/Libraries/Event.lua @@ -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 --------------------------------------------------------------------------------------------------------