fifo.lua 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. -- A generic fifo module. See docs/lua-modules/fifo.md for use examples.
  2. local tr, ti = table.remove, table.insert
  3. -- Remove an element and pass it to k, together with a boolean indicating that
  4. -- this is the last element in the queue; if that returns a value, leave that
  5. -- pending at the top of the fifo.
  6. --
  7. -- If k returns nil, the fifo will be advanced. Moreover, k may return a
  8. -- second result, a boolean, indicating "phantasmic" nature of this element.
  9. -- If this boolean is true, then the fifo will advance again, passing the next
  10. -- value, if there is one, to k, or priming itself for immediate execution at
  11. -- the next call to queue.
  12. --
  13. -- If the queue is empty, do not invoke k but flag it to enable immediate
  14. -- execution at the next call to queue.
  15. --
  16. -- Returns 'true' if the queue contained at least one non-phantom entry,
  17. -- 'false' otherwise.
  18. local function dequeue(q,k)
  19. if #q > 0
  20. then
  21. local new, again = k(q[1], #q == 1)
  22. if new == nil
  23. then tr(q,1)
  24. if again then return dequeue(q, k) end -- note tail call
  25. else q[1] = new
  26. end
  27. return true
  28. else q._go = true ; return false
  29. end
  30. end
  31. -- Queue a on queue q and dequeue with `k` if the fifo had previously emptied.
  32. local function queue(q,a,k)
  33. ti(q,a)
  34. if k ~= nil and q._go then q._go = false; dequeue(q, k) end
  35. end
  36. -- return a table containing just the FIFO constructor
  37. return {
  38. ['new'] = function()
  39. return { ['_go'] = true ; ['queue'] = queue ; ['dequeue'] = dequeue }
  40. end
  41. }