Самый простой способ заставить скрипт lua подождать / приостановить / уснуть / заблокировать на несколько секунд? - PullRequest
30 голосов
/ 23 июня 2009

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

  • sleep - остановить все действия в потоке

  • пауза / ожидание - не переходите к следующему команда, но разрешить другой код в заявка на продолжение

  • блок - не переходить к следующей команде, пока текущий возвращается

И я читал, что

while os.clock()<time_point do 
--nothing
end

съедает процессорное время.

Есть предложения? Я пропускаю вызов API?

ОБНОВЛЕНИЕ : я написал этот вопрос давным-давно, пытаясь заставить WOW Lua воспроизводить действия по расписанию (то есть стоять, ждать 1 секунду, танцевать, ждать 2 секунды, сидеть. Без пауз эти происходит почти все за одну и ту же четверть секунды.) Как оказалось, WOW преднамеренно отключил практически все, что позволяет выполнять действия на часах, потому что это может сломать игру или включить ботов. Я рассчитывал воссоздать После того, как часы были убраны, мне нужно было сделать что-нибудь сумасшедшее, например, создать рабочий массив (с действием и временем выполнения), а затем зарегистрировать обработчик событий для нескольких общих событий, таких как перемещение мыши, затем в даже обработчик, обработайте любое действие, время которого пришло. Обработчик события фактически не происходил бы каждые X миллисекунд, но если бы он происходил каждые 2-100 мс, он был бы достаточно близок. К сожалению, я никогда не пробовал.

Ответы [ 18 ]

20 голосов
/ 07 июля 2009

[Я собирался опубликовать это как комментарий к сообщению Джона Кромарти , но не понял, что вы не можете использовать форматирование в комментарии.]

Я согласен. Перетаскивание его в оболочку с помощью os.execute () определенно будет работать, но в целом выполнение вызовов оболочки стоит дорого. Свертывание некоторого C-кода будет намного быстрее во время выполнения. В C / C ++ в системе Linux вы можете использовать:

static int lua_sleep(lua_State *L)
{
    int m = static_cast<int> (luaL_checknumber(L,1));
    usleep(m * 1000); 
    // usleep takes microseconds. This converts the parameter to milliseconds. 
    // Change this as necessary. 
    // Alternatively, use 'sleep()' to treat the parameter as whole seconds. 
    return 0;
}

Затем, в основном, выполните:

lua_pushcfunction(L, lua_sleep);
lua_setglobal(L, "sleep");

где "L" - ваш lua_State. Затем в вашем Lua-скрипте, вызываемом из C / C ++, вы можете использовать свою функцию, вызывая:

sleep(1000) -- Sleeps for one second
18 голосов
/ 31 октября 2011

Если вам случится использовать LuaSocket в вашем проекте, или вы просто установили его и не возражаете против его использования, вы можете использовать функцию socket.sleep(time), которая спит для заданное количество времени (в секундах).

Это работает как в Windows, так и в Unix, и вам не нужно компилировать дополнительные модули.

Я должен добавить, что функция поддерживает дробные секунды в качестве параметра, то есть socket.sleep(0.5) будет спать полсекунды. Он использует Sleep() в Windows и nanosleep() в других местах, поэтому могут возникнуть проблемы с точностью Windows, когда time становится слишком низким.

10 голосов
/ 26 июня 2009

Вы не можете сделать это в чистом Lua без использования процессора, но есть простой непереносимый способ:

os.execute ("сон 1")

(это заблокирует)

Очевидно, что это работает только в операционных системах, для которых «sleep 1» является допустимой командой, например Unix, но не Windows.

8 голосов
/ 23 января 2012

для окон вы можете сделать это:

os.execute("CHOICE /n /d:y /c:yn /t:5")
7 голосов
/ 07 ноября 2012

Функция сна - Использование: sleep(1) -- sleeps for 1 second

local clock = os.clock
function sleep(n)  -- seconds
   local t0 = clock()
   while clock() - t0 <= n do
   end
end

Функция паузы - Использование: pause() -- pause and waits for the Return key

function pause()
   io.stdin:read'*l'
end

надеюсь, это то, что вам нужно! : D - Джо Д.Ф.

4 голосов
/ 04 июня 2014

Это не легче, чем это. Спящий режим может быть реализован в вашем FLTK или чем-то подобном, но он охватывает все лучшие способы выполнения стандартных видов системных снов без особых прерываний событий. Вот:

-- we "pcall" (try/catch) the "ex", which had better include os.sleep
-- it may be a part of the standard library in future Lua versions (past 5.2)
local ok,ex = pcall(require,"ex")
if ok then
   -- print("Ex")
   -- we need a hack now too? ex.install(), you say? okay
   pcall(ex.install)
   -- let's try something else. why not?
   if ex.sleep and not os.sleep then os.sleep = ex.sleep end
end

if not os.sleep then
   -- we make os.sleep
   -- first by trying ffi, which is part of LuaJIT, which lets us write C code
   local ok,ffi = pcall(require,"ffi")
   if ok then
      -- print("FFI")
      -- we can use FFI
      -- let's just check one more time to make sure we still don't have os.sleep
      if not os.sleep then
         -- okay, here is our custom C sleep code:
         ffi.cdef[[
            void Sleep(int ms);
            int poll(struct pollfd *fds,unsigned long nfds,int timeout);
         ]]
         if ffi.os == "Windows" then
            os.sleep = function(sec)
               ffi.C.Sleep(sec*1000)
            end
         else
            os.sleep = function(sec)
               ffi.C.poll(nil,0,sec*1000)
            end
         end
      end
   else
      -- if we can't use FFI, we try LuaSocket, which is just called "socket"
      -- I'm 99.99999999% sure of that
      local ok,socket = pcall(require,"socket")
      -- ...but I'm not 100% sure of that
      if not ok then local ok,socket = pcall(require,"luasocket") end
      -- so if we're really using socket...
      if ok then
         -- print("Socket")
         -- we might as well confirm there still is no os.sleep
         if not os.sleep then
            -- our custom socket.select to os.sleep code:
            os.sleep = function(sec)
               socket.select(nil,nil,sec)
            end
         end
      else
         -- now we're going to test "alien"
         local ok,alien = pcall(require,"alien")
         if ok then
         -- print("Alien")
         -- beam me up...
            if not os.sleep then
               -- if we still don't have os.sleep, that is
               -- now, I don't know what the hell the following code does
               if alien.platform == "windows" then
                  kernel32 = alien.load("kernel32.dll")
                  local slep = kernel32.Sleep
                  slep:types{ret="void",abi="stdcall","uint"}
                  os.sleep = function(sec)
                     slep(sec*1000)
                  end
               else
                  local pol = alien.default.poll
                  pol:types('struct', 'unsigned long', 'int')
                  os.sleep = function(sec)
                     pol(nil,0,sec*1000)
                  end
               end
            end
         elseif package.config:match("^\\") then
            -- print("busywait")
            -- if the computer is politically opposed to NIXon, we do the busywait
            -- and shake it all about
            os.sleep = function(sec)
               local timr = os.time()
               repeat until os.time() > timr + sec
            end
         else
            -- print("NIX")
            -- or we get NIXed
            os.sleep = function(sec)
               os.execute("sleep " .. sec)
            end
         end
      end
   end
end
3 голосов
/ 13 декабря 2012
require 'alien'

if alien.platform == "windows" then
  kernel32 = alien.load("kernel32.dll")
  sleep = kernel32.Sleep
  sleep:types{ret="void",abi="stdcall","uint"}
else
  -- untested !!!
  libc = alien.default
  local usleep = libc.usleep
  usleep:types('int', 'uint')
  sleep = function(ms)
    while ms > 1000 do
      usleep(1000)
      ms = ms - 1000
    end
    usleep(1000 * ms)
  end
end 

print('hello')
sleep(500)  -- sleep 500 ms
print('world')
3 голосов
/ 23 июня 2009

Я бы реализовал простую функцию, чтобы обернуть функцию сна хост-системы в C.

3 голосов
/ 26 июня 2009

Pure Lua использует только то, что соответствует стандарту ANSI C. Модуль lposix Luiz Figuereido содержит большую часть того, что вам нужно для более системных действий.

3 голосов
/ 25 июня 2011

Для второго запроса, пауза / ожидание, когда вы останавливаете обработку в Lua и продолжаете запускать ваше приложение, вам нужны сопрограммы. Вы получите код C, подобный следующему:

Lthread=lua_newthread(L);
luaL_loadfile(Lthread, file);
while ((status=lua_resume(Lthread, 0) == LUA_YIELD) {
  /* do some C code here */
}

и в Lua у вас есть следующее:

function try_pause (func, param)
  local rc=func(param)
  while rc == false do
    coroutine.yield()
    rc=func(param)
  end
end

function is_data_ready (data)
  local rc=true
  -- check if data is ready, update rc to false if not ready
  return rc
end

try_pause(is_data_ready, data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...