opus/sys/apis/event.lua

178 lines
3.5 KiB
Lua

local Util = require('util')
local Event = {
uid = 1, -- unique id for handlers
}
local eventHandlers = {
namedTimers = {}
}
-- debug purposes
function Event.getHandlers()
return eventHandlers
end
function Event.addHandler(type, f)
local event = eventHandlers[type]
if not event then
event = {}
event.handlers = {}
eventHandlers[type] = event
end
local handler = {
uid = Event.uid,
event = type,
f = f,
}
Event.uid = Event.uid + 1
event.handlers[handler.uid] = handler
return handler
end
function Event.removeHandler(h)
if h and h.event then
eventHandlers[h.event].handlers[h.uid] = nil
end
end
function Event.queueTimedEvent(name, timeout, event, args)
Event.addNamedTimer(name, timeout, false,
function()
os.queueEvent(event, args)
end
)
end
function Event.addNamedTimer(name, interval, recurring, f)
Event.cancelNamedTimer(name)
eventHandlers.namedTimers[name] = Event.addTimer(interval, recurring, f)
end
function Event.getNamedTimer(name)
return eventHandlers.namedTimers[name]
end
function Event.cancelNamedTimer(name)
local timer = Event.getNamedTimer(name)
if timer then
timer.enabled = false
Event.removeHandler(timer)
end
end
function Event.isTimerActive(timer)
return timer.enabled and
os.clock() < timer.start + timer.interval
end
function Event.addTimer(interval, recurring, f)
local timer = Event.addHandler('timer',
function(t, id)
if t.timerId ~= id then
return
end
if t.enabled then
t.fired = true
t.cf(t, id)
end
if t.recurring then
t.fired = false
t.start = os.clock()
t.timerId = os.startTimer(t.interval)
else
Event.removeHandler(t)
end
end
)
timer.cf = f
timer.interval = interval
timer.recurring = recurring
timer.start = os.clock()
timer.enabled = true
timer.timerId = os.startTimer(interval)
return timer
end
function Event.removeTimer(h)
Event.removeHandler(h)
end
function Event.blockUntilEvent(event, timeout)
return Event.waitForEvent(event, timeout, os.pullEvent)
end
function Event.waitForEvent(event, timeout, pullEvent)
pullEvent = pullEvent or Event.pullEvent
local timerId = os.startTimer(timeout)
repeat
local e, p1, p2, p3, p4 = pullEvent()
if e == event then
return e, p1, p2, p3, p4
end
until e == 'timer' and p1 == timerId
end
local exitPullEvents = false
local function _pullEvents()
--exitPullEvents = false
while true do
local e = Event.pullEvent()
if exitPullEvents or e == 'terminate' then
break
end
end
end
function Event.sleep(t)
local timerId = os.startTimer(t or 0)
repeat
local event, id = Event.pullEvent()
until event == 'timer' and id == timerId
end
function Event.pullEvents(...)
local routines = { ... }
if #routines > 0 then
parallel.waitForAny(_pullEvents, ...)
else
_pullEvents()
end
end
function Event.exitPullEvents()
exitPullEvents = true
os.sleep(0)
end
function Event.pullEvent(eventType)
local e = { os.pullEventRaw(eventType) }
return Event.processEvent(e)
end
function Event.processEvent(pe)
local e, p1, p2, p3, p4, p5 = unpack(pe)
local event = eventHandlers[e]
if event then
local keys = Util.keys(event.handlers)
for _,key in pairs(keys) do
local h = event.handlers[key]
if h then
h.f(h, p1, p2, p3, p4, p5)
end
end
end
return e, p1, p2, p3, p4, p5
end
return Event