LINUX.ORG.RU

как реализовать логику работы «таймера delphi» в lua ?


0

1

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

★★★★

насколько я знаю, прервать выполнение луа скрипта нельзя, поэтому как-то нужно разбить алгоритм, всунув куда-то проверку на таймер.

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

Интересует удачный опыт в реализации такой же же или аналогичной задачи. На словах ТЕОРЕТИЧЕСКИ я понимаю - что можно сделать отдельную thread в ней вызвать функцию аналогичную sleep если нет поставь модуль и т.д. При необходимости почитать интернет, поковыряться. Если у кого то был опыт и не жалко привести кусок кода, вот цель моего поста.

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от ilovewindows

ну а потоки в этом чудо языке есть, и sleep ?

Нету, потому что этого всего нет в стандарте ANSI C, это только часть POSIX.

На скорую руку sleep можно реализовать через busy waiting с вызовом os.clock.

А для того, что хочет ТС, можно посмотреть на Lua Lanes, на lalarm отсюда или на другие решения.

proud_anon ★★★★★
()
Ответ на: комментарий от ilovewindows

Потоки то есть

Откуда? Корутины только есть, которые работают в одном потоке. Хотя, наверное, если постараться, можно их распараллелить. Но Lanes делает не так, а запускает несколько параллельных states, которые между собой могут только обмениваться сообщениями, ради защиты от гонок.

но народ вроде как извращается через внешнюю библиотеку, так понял

Ну, что значит извращается? Не извращается, а просто вызывает sleep.

proud_anon ★★★★★
()
Ответ на: комментарий от tnodir

да.
раз в 15 сек планируется переопределять файл в который пишутся данные. т.е. программа читает STDIN и перенаправляет вывод по очереди в один из 4 х открытых файлов.

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от buddhist

как я понял из принципа действия функции alarm все равно нужен механизм запускающий ее параллельно, в том примере который идет вместе с функцией выполнение программы приостанавливается

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от buddhist

прерывать основной алгоритм можно - 1 раз в 15 сек - (необходимо в основном алгоритме менять указатель файла для «непрерывного» вывода)
если бы нельзя было прерывать - то и задачи бы не было.

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

раз в 15 сек планируется переопределять файл в который пишутся данные

Нельзя вместо таймера, каждый раз при записи проверять, не надо ли сменить файл? Напр.:

do
  local files = {file1, file2, file3, file4}
  local file_no = 1
  local file = files[file_no]
  local ROTATON_SECONDS = 15
  local rotate_time = os.time() + ROTATON_SECONDS

  function out(data)
    local now = os.time()
    if os.difftime(now, rotate_time) > 0 then
      rotate_time = now + ROTATON_SECONDS
      file_no = (file_no + 1) % #files
    end
    return file.write(data)
  end
end

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

s /ROTATON_SECONDS/ROTATION_SECONDS/g;

      file_no = (file_no + 1) % #files
+     file = files[file_no]
    end

Если делать через таймер, то: - alarm не работает в windows; - хуки (для прерывания основного алгоритма) не работают в LuaJIT, когда JIT включен.

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

данный алгоритм работать по сути будет, но через этот код будут пролетать по полтора миллиона строк в минуту. На вызов функции out будет тратиться время равное количеству прошедших строк. мне думается что если прерывать алгоритм раз в 15 сек то это будет эффективнее - собственно и поэтому возник вопрос. С другой стороны не факт что отдельная thread будет работать на другом физическом процессоре.

а разве этот алгоритм можно реализовать через alarm?

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

а разве этот алгоритм можно реализовать через alarm?

Обработчик SIGALRM ставит хук, прерывается основной поток и вызывается коллбек.

Я бы сделал с помощью биб-ки luasys [1] так:

======
#!/usr/bin/env lua

local sys = require"sys"

local thread = sys.thread
thread.init()

local out_fd

-- File rotation
local mutex = thread.pipe()
do
  local function create_file(path)
    local fd = sys.handle()
    return assert(fd:open(path, "w", nil, "creat"))
  end

  local files = {
    create_file("out1.txt"),
    create_file("out2.txt")
  }
  local nfiles = #files
  local index = 0

  out_fd = files[1]

  local function rotation()
    while true do
      local res = mutex:get(20)  -- 10 milliseconds
      if res then break end
      index = (index + 1) % nfiles
      out_fd = files[index + 1]
    end
  end

  assert(thread.run(rotation))
end

-- Process
for i = 1, 10000 do
  out_fd:write(i, '\n')
end

mutex:put(1)  -- stop rotation thread
======

Важно использовать ф-ции luasys для работы с файлами в основном алгоритме, т.к. нужно передать управление другой активной нити, если есть такая.

[1] https://github.com/tnodir/luasys

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

Обработчик SIGALRM ставит хук, прерывается основной поток и вызывается коллбек.

Значит я не правильно понял смысл этого модуля. и если так то по сути он должен подойти для моей задачи.

luasys (https://github.com/tnodir/luasys) не собирается под lua-5.1 на linux, так должно быть?

И еще вопрос, каким модулем внедряется в lua поддержка обработки сигналов (HUP,TERM,KILL и т.д.)?

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

luasys (https://github.com/tnodir/luasys) не собирается под lua-5.1 на linux

В Makefile надо вместо lua-5.2.1 указать lua-5.1

И еще вопрос, каким модулем внедряется в lua поддержка обработки сигналов (HUP,TERM,KILL и т.д.)?

Много таких, напр.: - https://github.com/msva/lua-signal - http://peterodding.com/code/lua/apr

Многие модули обрабатывают сигналы через хуки, которые не будут работать в LuaJIT.

В luasys можно ловить сигналы SIGINT, SIGHUP, SIGQUIT, SIGTERM в *nix и windows через sys.event_queue(). Пример: https://github.com/tnodir/luasys/blob/master/test/event/test_evq.lua

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

В Makefile надо вместо lua-5.2.1 указать lua-5.1


#LUA= /tmp/lua-5.2.1
LUA= /usr/src/lua-5.1.4

все равно не собирается

# make linux
make all MYCFLAGS="-DUSE_EPOLL -DUSE_EVENTFD" MYLIBS="-lrt"
make[1]: Entering directory `/usr/src/luasys-master/src'
gcc -O2 -fPIC -DNDEBUG -W -Wall -Wextra -pedantic -Waggregate-return -Wbad-function-cast -Wcast-align -Wcast-qual -Wdeclaration-after-statement -Wdisabled-optimization -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wshadow -Wsign-compare -Wstrict-prototypes -Wundef -Wwrite-strings  -DUSE_EPOLL -DUSE_EVENTFD -I/usr/src/lua-5.1.4/src   -c -o luasys.o luasys.c
In file included from event/evq.h:16,
                 from event/evq.c:3,
                 from sys_evq.c:21,
                 from luasys.c:231:
event/epoll.h:8:25: error: sys/eventfd.h: No such file or directory
In file included from event/evq.c:65,
                 from sys_evq.c:21,
                 from luasys.c:231:
event/epoll.c: In function ‘evq_init’:
event/epoll.c:23: warning: implicit declaration of function ‘eventfd’
event/epoll.c:23: warning: nested extern declaration of ‘eventfd’
event/epoll.c:23: error: ‘EFD_NONBLOCK’ undeclared (first use in this function)
event/epoll.c:23: error: (Each undeclared identifier is reported only once
event/epoll.c:23: error: for each function it appears in.)
event/epoll.c:23: error: ‘EFD_CLOEXEC’ undeclared (first use in this function)
make[1]: *** [luasys.o] Error 1
make[1]: Leaving directory `/usr/src/luasys-master/src'
make: *** [linux] Error 2

Используя LuaJIT можно значительно ускорить выполнение скриптов ?

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от proud_anon

c функцией alarm все получилось.
Спасибо за ответы, узнал много интересного

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

Используя LuaJIT можно значительно ускорить выполнение скриптов ?

Да [1], если код в основном написан на Lua и относительно мало вызовов C-функций. Даже без JIT, интерпретатор LuaJIT работает быстрее.

[1] http://luajit.org/performance_x86.html

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

Скомпилировался модуль. Пример заработал, разбираюсь что к чему. А не подкинете ссылок на теорию этого модуля как устроено, как работает?

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

Документации пока нет. Старался реализовать системные функции кросплатформенно.

Вызовы системных ф-ций обёрнуты в unlock(vm)/lock(vm), т.е. с одним Lua VM может работать только одна нить (GIL). VM создаются через thread.runvm().

Мультиплексор событий: sys.event_queue(). Есть события от сокетов, изменения файлов/директорий, таймеры и т.п.

В общем, в исходниках в конце каждого файла есть список экспортируемых функций.

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

а на какой емайл можно прислать вопрос?

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