Advertisement
joebodo

Forums.event.lua

Aug 4th, 2017
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.10 KB | None | 0 0
  1. local Event = {
  2.   uid       = 1,       -- unique id for handlers
  3.   routines  = { },     -- coroutines
  4.   types     = { },     -- event handlers
  5.   timers    = { },     -- named timers
  6.   terminate = false,
  7. }
  8.  
  9. local Routine = { }
  10.  
  11. function Routine:isDead()
  12.   if not self.co then
  13.     return true
  14.   end
  15.   return coroutine.status(self.co) == 'dead'
  16. end
  17.  
  18. function Routine:terminate()
  19.   if self.co then
  20.     self:resume('terminate')
  21.   end
  22. end
  23.  
  24. function Routine:resume(event, ...)
  25.  
  26.   if not self.co then
  27.     error('Cannot resume a dead routine')
  28.   end
  29.  
  30.   if not self.filter or self.filter == event or event == "terminate" then
  31.     local s, m = coroutine.resume(self.co, event, ...)
  32.  
  33.     if coroutine.status(self.co) == 'dead' then
  34.       self.co = nil
  35.       self.filter = nil
  36.       Event.routines[self.uid] = nil
  37.     else
  38.       self.filter = m
  39.     end
  40.  
  41.     if not s and event ~= 'terminate' then
  42.       error('\n' .. (m or 'Error processing event'))
  43.     end
  44.  
  45.     return s, m
  46.   end
  47.  
  48.   return true, self.filter
  49. end
  50.  
  51. local function nextUID()
  52.   Event.uid = Event.uid + 1
  53.   return Event.uid - 1
  54. end
  55.  
  56. function Event.on(event, fn)
  57.  
  58.   local handlers = Event.types[event]
  59.   if not handlers then
  60.     handlers = { }
  61.     Event.types[event] = handlers
  62.   end
  63.  
  64.   local handler = {
  65.     uid     = nextUID(),
  66.     event   = event,
  67.     fn      = fn,
  68.   }
  69.   handlers[handler.uid] = handler
  70.   setmetatable(handler, { __index = Routine })
  71.  
  72.   return handler
  73. end
  74.  
  75. function Event.off(h)
  76.   if h and h.event then
  77.     Event.types[h.event][h.uid] = nil
  78.   end
  79. end
  80.  
  81. local function addTimer(interval, recurring, fn)
  82.  
  83.   local timerId = os.startTimer(interval)
  84.   local handler
  85.  
  86.   handler = Event.on('timer', function(t, id)
  87.     if timerId == id then
  88.       fn(t, id)
  89.       if recurring then
  90.         timerId = os.startTimer(interval)
  91.       else
  92.         Event.off(handler)
  93.       end
  94.     end
  95.   end)
  96.  
  97.   return handler
  98. end
  99.  
  100. function Event.onInterval(interval, fn)
  101.   return addTimer(interval, true, fn)
  102. end
  103.  
  104. function Event.onTimeout(timeout, fn)
  105.   return addTimer(timeout, false, fn)
  106. end
  107.  
  108. function Event.addNamedTimer(name, interval, recurring, fn)
  109.   Event.cancelNamedTimer(name)
  110.   Event.timers[name] = addTimer(interval, recurring, fn)
  111. end
  112.  
  113. function Event.cancelNamedTimer(name)
  114.   local timer = Event.timers[name]
  115.   if timer then
  116.     Event.off(timer)
  117.   end
  118. end
  119.  
  120. function Event.waitForEvent(event, timeout)
  121.   local timerId = os.startTimer(timeout)
  122.   repeat
  123.     local e = { os.pullEvent() }
  124.     if e[1] == event then
  125.       return table.unpack(e)
  126.     end
  127.   until e[1] == 'timer' and e[2] == timerId
  128. end
  129.  
  130. function Event.addRoutine(fn)
  131.   local r = {
  132.     co  = coroutine.create(fn),
  133.     uid = nextUID()
  134.   }
  135.   setmetatable(r, { __index = Routine })
  136.   Event.routines[r.uid] = r
  137.  
  138.   r:resume()
  139.  
  140.   return r
  141. end
  142.  
  143. function Event.pullEvents(...)
  144.  
  145.   for _, fn in ipairs({ ... }) do
  146.     Event.addRoutine(fn)
  147.   end
  148.  
  149.   repeat
  150.     local e = Event.pullEvent()
  151.   until e[1] == 'terminate'
  152. end
  153.  
  154. function Event.exitPullEvents()
  155.   Event.terminate = true
  156.   os.sleep(0)
  157. end
  158.  
  159. local function processHandlers(event)
  160.  
  161.   local handlers = Event.types[event]
  162.   if handlers then
  163.     for _,h in pairs(handlers) do
  164.       if not h.co then
  165.         -- callbacks are single threaded (only 1 co per handler)
  166.         h.co = coroutine.create(h.fn)
  167.         Event.routines[h.uid] = h
  168.       end
  169.     end
  170.   end
  171. end
  172.  
  173. local function tokeys(t)
  174.   local keys = { }
  175.   for k in pairs(t) do
  176.     keys[#keys+1] = k
  177.   end
  178.   return keys
  179. end
  180.  
  181. local function processRoutines(...)
  182.  
  183.   local keys = tokeys(Event.routines)
  184.   for _,key in ipairs(keys) do
  185.     local r = Event.routines[key]
  186.     if r then
  187.       r:resume(...)
  188.     end
  189.   end
  190. end
  191.  
  192. function Event.pullEvent(eventType)
  193.  
  194.   while true do
  195.     local e = { os.pullEventRaw() }
  196.  
  197.     processHandlers(e[1])
  198.     processRoutines(table.unpack(e))
  199.  
  200.     if Event.terminate or e[1] == 'terminate' then
  201.       Event.terminate = false
  202.       return { 'terminate' }
  203.     end
  204.  
  205.     if not eventType or e[1] == eventType then
  206.       return e
  207.     end
  208.   end
  209. end
  210.  
  211. return Event
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement