LINUX.ORG.RU

Lua, 2 разных потока.

 , ,


1

1

Приветствую! (далее длинный пост)

Есть некоторая тестовая утилита, которая расширяется луашечкой. В луа импортируются нужные функции/таблицы и далее есть определенная функция уже в самом скрипте, которая запускается после загрузки этого скрипта.

то есть что-то типа

function main(args)
--- тут все, что нужно
end

Все просто сделали load скрипту и выполнили main.

Так же есть события, которые приходят из другого потока и несут нужную инфу. Хочу протянуть возможность регистрации/обработки этих событий.

Совершенно понятно, что дернуть какой-то вызов из другого потока в том же lua_State, в котором исполняется вызов main я не могу. Поэтому я создаю другой lua_State, от главного event_state = lua_newthread(main_state) и, делаю вызовы уже в нем. Пример скрипта

function handler( data )
--- тут обработка события
end

function main( args )

    client.subscribe("on_data_ready", handler) -- тут подписка на событие

end

И это работает! Событие приходит, исполняется в своем lua_State и, казалось бы, ничего не падает. Но что-то тут не так, потому как main_state и event_state делят глобальные объекты и, стало быть должны как-то это разруливать.

Второй момент - это передача параметров с подпиской на событие. Например

function handler( data, param ) -- param тут {"Hello!", "blabla"}
--- тут обработка события
end

function main( args )

    -- тут подписка на событие с доп параметром
    client.subscribe("on_data_ready", handler, {"Hello!", "blabla"}) 

end

параметры я сохраняю как референсы через LUA_REGISTRYINDEX и потом передаю их при вызове обработчика в назначенную функцию. И снова вопрос в том, что LUA_REGISTRYINDEX это одна таблица, и стало быть, ее нужно как-то лочить.

+ у меня есть есть возможность отследить наступление события в event_state из main_state и прочитать, что вернула function handler, опять же через референсы. Стало быть если я в событии делаю return reslut1, reslut2, reslut3 и потом сохраняю их в LUA_REGISTRYINDEX, а в этот момент main_state делает подписку на другое событие и параметры тоже сохраняет в LUA_REGISTRYINDEX, то будет не весело и все навернется.

Собственно в этом вопрос. Как такое c lua делать правильно? И можно ли вообще такое делать с lua? Если нужно как-то лочить таблицы, то нужно ли это делать в _каждом вызове_, который потенциально может быть дернут из 2 разных потоков?

★★

lua_State полностью однопоточный, если тебе надо вызывать код из разных потоков надо все вызовы обернуть в один большой лок.

lua_newthread(main_state)

создаёт новую coroutine, которая может быть использована для кооперативной многозадачности в пределах одного lua_State. «Настоящие» потоки в ней не используются.

anonymous
()
Ответ на: комментарий от anonymous

Anonim prav. луа не для таких задач. Возможно стоит пересмотреть архитектуру. Например все события исполнять после main в евентлупе, а результаты обработчиков сохранять где-то в глобальном месте. Ну и вообще подумать так ли нужно ждать результатов событий. + при такой схеме можно таймеры в этот евентлуп кидать и вообще любые функции.

anonymous
()

А может лучше события из C кода класть в очередь, а в main сделать Event loop, который эти событий будет вытягивать?

anonymous
()
Ответ на: комментарий от anonymous

ну, я надеялся, что есть какой-то способ и я что-то упустил.

В общем буду делать очередь событий и просто выполнять их уже после main. так будет правильнее всего, на мой взгляд.

Всем спасибо.

ossa ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.