В общем ситуация такова:
Есть 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