Je n'arrive pas à comprendre comment faire en sorte que Lua fasse des tours de chronométrage courants, tels que
sleep - arrête toute action sur le fil
pause/wait - n'entrez pas dans la prochaine commande mais laissez un autre code de l'application continuer
block - ne passe pas à la commande suivante avant le retour de la commande courante
Et j'ai lu qu'un
while os.clock()<time_point do
--nothing
end
mange du temps CPU.
Aucune suggestion? Y a-t-il un appel d'API qui me manque?
UPDATE: J'ai écrit cette question il y a longtemps en essayant de demander à WOW Lua de rejouer des actions selon un calendrier (par exemple, rester debout, attendre 1 seconde, danser, attendre 2 secondes, s'asseoir. Sans pause, elles se produisent presque toutes dans le même quart de seconde.) Comme il s’est avéré, WOW a volontairement désactivé pratiquement tout ce qui permet d’agir sur une horloge, car cela pourrait interrompre le jeu ou permettre aux robots de jouer. Je pensais que pour recréer une horloge une fois qu'elle avait été enlevée, je devais faire quelque chose de fou, comme créer un tableau de travail (avec une action et une heure d'exécution), puis enregistrer un gestionnaire d'événements sur plusieurs événements courants. , comme le déplacement de la souris, puis dans le gestionnaire pair, traite toute action dont le temps est venu. Le gestionnaire d'événements ne se produirait pas toutes les X millisecondes, mais s'il se produisait toutes les 2 à 100 ms, cela serait suffisamment proche. Malheureusement, je n'ai jamais essayé.
Cela ne devient pas plus facile que cela. Le sommeil peut être implémenté dans votre FLTK ou autre, mais cela couvre toutes les meilleures façons de faire le type de sommeil standard du système sans interruption d’événement spéciale. Voir:
-- 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
[J'allais publier ceci sous forme de commentaire sur John Cromartie's post, mais je ne savais pas que vous ne pouviez pas utiliser la mise en forme dans un commentaire.]
Je suis d'accord. Le déposer dans un shell avec os.execute () fonctionnera certainement, mais en général, les appels au shell sont coûteux. Envelopper du code C sera beaucoup plus rapide au moment de l'exécution. En C/C++ sur un système Linux, vous pouvez utiliser:
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;
}
Ensuite, en gros, faites:
lua_pushcfunction(L, lua_sleep);
lua_setglobal(L, "sleep");
où "L" est votre lua_State. Ensuite, dans votre script Lua appelé à partir de C/C++, vous pouvez utiliser votre fonction en appelant:
sleep(1000) -- Sleeps for one second
Si vous utilisez LuaSocket dans votre projet, ou si vous l'avez simplement installé et que cela ne vous dérange pas, vous pouvez utiliser la fonction socket.sleep(time)
qui dort pendant une durée donnée (en secondes) .
Cela fonctionne à la fois sous Windows et Unix, et vous n'avez pas à compiler de modules supplémentaires.
Je devrais ajouter que la fonction prend en charge la fraction de seconde en tant que paramètre, c’est-à-dire que socket.sleep(0.5)
dormira une demi-seconde. Il utilise Sleep()
sous Windows et nanosleep()
ailleurs. Vous risquez donc d’être confronté à des problèmes d’exactitude de Windows lorsque time
devient trop faible.
Vous ne pouvez pas le faire en Lua pur sans manger de processeur, mais il existe un moyen simple et non portable:
os.execute ("sleep 1")
(ça va bloquer)
Évidemment, cela ne fonctionne que sur les systèmes d'exploitation pour lesquels "sleep 1" est une commande valide, par exemple Unix, mais pas Windows.
pour les fenêtres, vous pouvez faire ceci:
os.execute("CHOICE /n /d:y /c:yn /t:5")
Fonction de veille - Utilisation: sleep(1) -- sleeps for 1 second
local clock = os.clock
function sleep(n) -- seconds
local t0 = clock()
while clock() - t0 <= n do
end
end
Fonction de pause - Utilisation: pause() -- pause and waits for the Return key
function pause()
io.stdin:read'*l'
end
espérons que c'est ce dont vous aviez besoin! : D - Joe DF
Pure Lua utilise uniquement ce qui est dans la norme ANSI C. Le module lposix module de Luiz Figuereido contient une grande partie de ce dont vous avez besoin pour faire des choses plus systématiques.
Je mettrais en œuvre une fonction simple pour envelopper la fonction de sommeil du système hôte en C.
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')
Pour la deuxième demande, pause/attente, lorsque vous arrêtez le traitement dans Lua et continuez à exécuter votre application, vous avez besoin de coroutines. Vous vous retrouvez avec un code C comme celui-ci:
Lthread=lua_newthread(L);
luaL_loadfile(Lthread, file);
while ((status=lua_resume(Lthread, 0) == LUA_YIELD) {
/* do some C code here */
}
et à Lua, vous avez:
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)
Vous pouvez utiliser:
os.execute("sleep 1") -- I think you can do every command of CMD using os.execute("command")
ou vous pouvez utiliser:
function wait(waitTime)
timer = os.time()
repeat until os.time() > timer + waitTime
end
wait(YourNumberHere)
Je suis d’accord avec John sur l’enveloppement de la fonction de veille .. Vous pouvez également utiliser cette fonction de veille enveloppée pour implémenter une fonction de pause dans Lua (qui dormirait simplement puis vérifierait si une condition particulière a changé de temps en temps). Une alternative consiste à utiliser des crochets.
Je ne suis pas tout à fait sûr de ce que vous entendez par votre troisième puce (les commandes ne sont-elles généralement pas terminées avant que la suivante ne soit exécutée?), Mais les crochets peuvent également vous aider.
Voir: Question: Comment puis-je terminer un fil Lua proprement? pour un exemple d'utilisation de crochets.
Vous voulez win.Sleep(milliseconds)
, il me semble.
Ouais, vous ne voulez certainement pas faire une attente occupée comme vous le décrivez.
Il est également facile d’utiliser Alien comme wrapper libc/msvcrt:
> luarocks install alien
Puis de Lua:
require 'alien'
if alien.platform == "windows" then
-- untested!!
libc = alien.load("msvcrt.dll")
else
libc = alien.default
end
usleep = libc.usleep
usleep:types('int', 'uint')
function sleep(ms)
while ms > 1000 do
usleep(1000)
ms = ms - 1000
end
usleep(1000 * ms)
end
print('hello')
sleep(500) -- sleep 500 ms
print('world')
Avertissement du lecteur: Je n'ai pas essayé ceci sous MSWindows; Je ne sais même pas si msvcrt a un usleep ()
J'ai commencé avec Lua mais, ensuite, j'ai découvert que je voulais voir les résultats plutôt que simplement le bon vieux flash en ligne de commande. Donc, je viens d'ajouter la ligne suivante à mon fichier et hop, la norme:
please press any key to continue...
os.execute("PAUSE")
Mon exemple de fichier n’est qu’une impression, puis une pause, donc je suis sûr que vous n’avez pas besoin de la publier ici.
Je ne suis pas sûr des implications en termes de processeur d'un processus en cours d'exécution pour un script complet. Cependant, arrêter le code en cours de débogage pourrait être utile.
Je crois que pour Windows, vous pouvez utiliser: os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul
comme un simple timer . (Supprimez le "<>" lors de l'insertion de l'heure en millisecondes) (il y a un espace entre le reste du code et >nul
cy = function()
local T = os.time()
coroutine.yield(coroutine.resume(coroutine.create(function()
end)))
return os.time()-T
end
sleep = function(time)
if not time or time == 0 then
time = cy()
end
local t = 0
repeat
local T = os.time()
coroutine.yield(coroutine.resume(coroutine.create(function() end)))
t = t + (os.time()-T)
until t >= time
end
Cela devrait fonctionner:
os.execute("PAUSE")