You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua51.lua 1.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. --
  2. -- Minetest asyncio: Lua 5.1 workarounds
  3. --
  4. local rawequal = rawequal
  5. minetest.log('warning', '[asyncio] LuaJIT not installed, asyncio.iter() ' ..
  6. 'will be less efficient.')
  7. -- Helper functions
  8. local function pack_len(...)
  9. local res = {...}
  10. res.length = select('#', ...)
  11. return res
  12. end
  13. local function unpack_len(t, i)
  14. i = i or 1
  15. if i <= t.length then
  16. return t[i], unpack_len(t, i + 1)
  17. end
  18. end
  19. -- A workaround for non-LuaJIT Lua 5.1
  20. -- Lua 5.1 does not allow coroutine.yield() inside iterators.
  21. function asyncio.iter(func, ...)
  22. local iter = asyncio._iter_start(func, ...)
  23. -- Fetch all values first
  24. local t = {}
  25. while true do
  26. local msg = pack_len(iter())
  27. if msg[1] == nil then break end
  28. table.insert(t, msg)
  29. end
  30. iter = nil
  31. -- Get the values
  32. return function()
  33. local msg = table.remove(t, 1)
  34. if type(msg) == 'table' then
  35. return unpack_len(msg)
  36. end
  37. end
  38. end
  39. -- A pcall() workaround/hack.
  40. local last_error = ...
  41. assert(type(last_error) == 'table')
  42. local function pcall_hack(func, ...)
  43. asyncio.yield(last_error, pack_len(func(...)))
  44. end
  45. function last_error.cleanup() last_error.msg = nil end
  46. local old_pcall = pcall
  47. function pcall(func, ...)
  48. if not asyncio.running then return old_pcall(func, ...) end
  49. local l, msg = asyncio._iter_start(pcall_hack, func, ...)()
  50. if l == last_error then
  51. return true, unpack_len(msg)
  52. elseif l ~= nil then
  53. return false, 'asyncio.yield() called outside of async iterator.'
  54. end
  55. return false, last_error.msg
  56. end