Как вынести набор команд в отдельную функцию в lua?

Есть вот такой код на lua:

require('sem')
semaphore = sem.open('RS485-3')
timeout = 10 * 2 
while not semaphore:trywait() and timeout > 0 do 
  sleep(0.5)
  timeout = timeout - 1
end


semaphore:post()
sem_local:close()


Реализует семафоры для того, чтобы разные потоки не конкурировали за порт. Проблема в том, что вот конкретно эти куски кода повторяются именно в таком виде довольно часто в разных скриптах, и хорошо бы их вынести в одно место, чтобы не копировать туда-сюда. Да и править если что - в одном месте, а не во многих. В идеале хочу функции вида semaphore_manager:wait и semaphore_manager:release, вместо этих строчек кода.

Пробовал сделать как-то так:
function semaphore_manager:wait(name)
require('sem')
semaphore = sem.open(name)
timeout = 10 * 2 
while not semaphore:trywait() and timeout > 0 do 
  sleep(0.5)
  timeout = timeout - 1
end 
return semaphore
end


function semaphore_manager:wait(sem_local)
sem_local:post()
sem_local:close()
end


но как-то не получилось, невнятно ругается. "loop or previous error loading module 'user.sem_manager'" и "attempt to index global 'sem_manager' (a nil value)"
Я понимаю, что это надо делать в самой библиотеке sem, которая это и реализует, но к ней доступа нет, а порядка в коде хочется.

И вдогонку вопрос примерно про тоже самое. Я делаю вот такую функцию:
function modbus(action, slave)
  if (action == 'connect') then
    require('luamodbus')
    mb = luamodbus.rtu()
    mb:open('/dev/RS485-3', 115200, 'N', 8, 1, 'H')
    mb:connect()
    mb:setslave(slave)
    local amount,  modbus_error = mb:readregisters(1)
    return amount, modbus_error
  elseif (action == 'disconnect') then
    mb:close()
  end
end


И вызываю ее соответственно
count_sensors, m_error = modbus('connect', slave_devices[i])
  modbus('disconnect')

Правильно ли я делаю? Вроде работает, но иногда глючит. Не может быть в этом дело?
  • Вопрос задан
  • 360 просмотров
Пригласить эксперта
Ответы на вопрос 1
mva
@mva
CEO, CTO, Lua/Gentoo/IPv6 Pioneer
1) для начала не стоит вызывать require внутри функций.

2) далее, не стоит засорять глобальное пространство (и автору модуля 'sem' скажите о том же, если его модуль умеет только экспортироваться в глобальное пространство, а не возвращать таблицу методов).

3) (вариация п.2) используйте локальные переменные как можно чаще, особенно внутри функций. Используйте глобальные только там, где это реально необходимо. Иначе будете напарываться на внезапные коллизии.

4) у меня, вообще, куча претензий к вашему коду в обоих вставках. От их количества мне уже просто хочется взять и переписать, ничего не объясняя, а потом отвечать на все вопросы о том почему так :)

5)
Правильно ли я делаю

С учётом всего вышеперечисленного, оно должно выглядеть совсем по-другому.
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы