Слушатели событий используются в каждой второй программе. Они удобны тем, что для них не нужно отводить отдельного цикла с ловлей ивентов и ставить кучу if'ов.
У них есть один недостаток: если их не удалить в конце программы, то они продолжат обрабатывать сигналы и выполнять действия. А это почти никогда не является полезным.
Особенно раздражает это поведение, когда программа завершается с ошибкой и до отключения слушателей дело и не дошло.
Можно ставить pcall
, но здесь мы заиспользуем потоки.
Потоки добавлены были в OpenOS 1.6.4 (OC 1.7+). Они задумывались как удобная имплементация многозадачности, но кроме того у них есть и одна интересная фича: все слушатели событий и таймеры, которые зарегистрированы в потоке, удаляются при его завершении.
Не важно, завершился ли поток из-за его отключения другим, ошибки или отсутствия команд для исполнения. Всё автоматически подчистится в любом случае.
Давайте воспользуемся ими для нашей цели. Для этого создадим один поток, в
котором зарегистрируем всех слушателей и начнём сам главный цикл. В другом
будем ловить нажатие Ctrl+C, потому что его поймать можно только через
event.pull
.
local event = require("event")
local thread = require("thread")
local mainThread = thread.create(function()
event.listen("key_down", function(evt, addr, key, code, user)
print("A key has been pressed!")
end)
while true do
print("do something")
os.sleep(0.5)
end
end)
local intThread = thread.create(function()
event.pull("interrupted")
end)
thread.waitForAny({mainThread, intThread})
os.exit(0)
Программа завершается, когда завершается любой из потоков: или закончился
главный цикл, или был пойман Ctrl+C. Поэтому используем thread.waitForAny
.
Кроме того, когда thread.waitForAny
завершится, один из потоков может
продолжать свою работу. Убить их и завершить программу позволяет функция
os.exit
.