@Mazino

Как организовать прерывания в однопоточном lua?

В общем ситуация такова:
Есть lua в 1 потоке, создать еще потоки нельзя. Я пытаюсь реализовать что-то на подобии event loop'а из JavaScript, а именно: чтение из socket'а, десериализация строки в событие с полезной нагрузкой или без, передача его в очередь и наконец обработка очереди. Получились 3 процесса(корутины), "параллельность" которых нужно эмитировать. первые 2 весьма просты , поскольку у них только 1 общий случай и оптимизировать их нет смысла, а вот с 3, где нужно обрабатывать очередь проблема, поскольку там может происходить что угодно вплоть до бесконечных циклов. Нужно "изобрести" механизм прерываний, для передачи управления из корутины выполнения. Т.е в моем понимании нужно в каждую вызванную функцию или цикл вставлять проверку не пора ли вернуть управление. Пока в идеях препроцессор или некая рантайм библиотека, которая сможет порождать уже обернутые функции и циклы. Поделитесь опытом или соображениями?
Пример кода:
event = {
  handlers = {
    message = { function(...) print(...) end },
    exec = { function(code) load(code, '=exec')() end }
  },
  listeners = {'message','exec' },
  on = function(self, name, cb, times, debounce)
    if not self['handlers'][name] then
      self['handlers'][name] = { cb }
      self['listeners'][#self.listeners + 1] = { name,#self['handlers'][name] }
    else
      table.insert(self['handlers'][name], cb)
    end
  end,
  fire = function(self, event, ...)
    if self['handlers'][event] then
      for _, v in ipairs(self['handlers'][event]) do
        v(event, ...)
      end
    end
  end,
  off = function(self, listener)
    for k, v in pairs(self['listeners']) do
      if v == listener then
        table.remove(self, k)
      end
    end
    self['handlers'][listener] = nil
  end
}
local queue = coroutine.wrap(
  function()
    while true do
      local buf = socket.read()
      if #buf > 0 then
        for _, v in pairs(split(buf, '\n')) do
          table.insert(messages, v)
        end
        coroutine.yield()
      end
    end
  end)

local dispatcher = coroutine.wrap(
  function()
    while true do
      while #messages > 0 do
        local msg = json.decode(messages:next())
        local t = {}
        local __event
        for k, v in pairs(msg) do
          if k == 'event' then
            __event = v
          else
            table.insert(t, v)
          end
        end
        phs(__event, json.encode(t))
      end
      coroutine.yield()
    end
  end)

local executor = coroutine.wrap(
  function()
    while true do
      event:fire(pls(0.01))
      coroutine.yield()
    end
  end)

while true do
  queue()
  dispatcher()
  executor()
end
  • Вопрос задан
  • 177 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы