Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local computer = require("computer")
- local event, handlers, interruptingKeysDown, lastInterrupt = {
- interruptingEnabled = true,
- interruptingDelay = 1,
- defaultInterruptingFunction = function()
- error("interrupted", 0)
- end,
- interruptingKeyCodes = {
- [29] = true,
- [46] = true,
- [56] = true
- },
- push = computer.pushSignal
- }, {}, {}, 0
- event.interruptingFunction = event.defaultInterruptingFunction
- 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")
- local handler = {
- callback = callback,
- times = times or mathHuge,
- interval = interval,
- nextTriggerTime = interval and computerUptime() + interval or 0
- }
- handlers[handler] = true
- return handler
- end
- function event.removeHandler(handler)
- checkArg(1, handler, "table")
- if handlers[handler] then
- handlers[handler] = nil
- return true
- else
- return false, "Handler with given table is not registered"
- end
- end
- function event.getHandlers()
- return handlers
- end
- function event.skip(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
- -- 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
- -- 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
- 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")
- local deadline = computerUptime() + (time or 0)
- repeat
- event.pull(deadline - computerUptime())
- until computerUptime() >= deadline
- end
- --------------------------------------------------------------------------------------------------------
- return event
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement