How does Lua realize millisecond delay?

If write:

(dosomething a)

repeat

until n = = 1

(dosomething b)

 the program will crash.But I don’t know how long a is going to execute, I want to judge every 200ms, like:

(dosomething a)

repeat

msleep (200)

until n = = = 1

(dosomething b)

msleep is a delay function. I want to ask how this msleep delay function should be written  to occupy the least system resources?

Look forward to your ideas

Do Not Use Non-Corona Timers

Do not use msleep()

Do Not Write Blocking Code

Do not write code like this or you will block the app and hang it. 

for i = 1, 1000000000000, do -- busy loop; blocks progress. end print("done")

Corona is single threaded and waits till your Lua scripts complete to continue.

Use Corona Timers (performWithDelay)
You need to user timers to delay an action:
https://docs.coronalabs.com/api/library/timer/index.html
https://docs.coronalabs.com/api/library/timer/performWithDelay.html

local function doit() print( "Current sim time: ", system.getTimer() ) end doit() doit() -- function reference passed directly timer.performWithDelay( 1000, doit ) -- closure used to call function timer.performWithDelay( 2000, function() doit() end ) -- closure used to delay execute arbitrary code timer.performWithDelay( 2500, function() print( "Current sim time: ", system.getTimer() ) end )

co-routines
Alternately, you need to use coroutines to suspend a section of code and resume it later.
 
https://www.lua.org/pil/9.1.html
 
I’m not showing how to do this.  I don’t actually suggest it and it isn’t immediately clear how it works.  i.e. It takes some study.

I will use the timer.performWithDelay function, but for some reasons, I need the delay function. Can the millisecond delay in the timer.performWithDelayfunction be extracted separately? If it is an extension library written by C, it can also be available

Can you say specifically what those “some reasons” are?

emmm…As a result of the design idea, I used the last Lua SDK to have a msleep (200) delay function, waiting for the 200ms to continue to execute the next sentence, so my design idea has always needed a delay function. Now I have changed my thinking to meet my needs, but I still want one if I can. Time delay function, I use C to expand the library is used in the C sleep function, is to hang up the program will lead to the interface card, I want a better function.

You can achieve the same results w/o msleep and then your code will work correctly with Corona instead of blocking.

Two choices:

  • timer.*
  • Co-routines

I don’t understand what you’re asking about the C-Api of a timer/msleep/other function.  Are you doing native coding?

You need to show us a small and clear example snippet of code (pseudo-code is OK) showing what you want to use this for.

formatyourcode.jpg

You should never, ever use a busy-wait loop (i.e. a while or for loop that just runs and does nothing). You will never ever get the same time since these loops execute as fast as they can, one CPU might finish twice as fast as another CPU.  Not to show my age, but I loved playing the old, F16 flight game on the PC way back when. Then I upgraded my PC and the game became completely unplayable because they used busy-wait loops to time things.   

Secondly, in particular for mobile devices, users have an expectation that when they click/tap something, the UI will be responsive. If you’re using sleep()'s and busy-wait’s that UI just won’t be responsive. It’s sort of the same concept that may struggle where they want to code a dedicated game loop, which in many cases isn’t needed because Corona is event driven. That desire to call a main() function to start things off just isn’t needed. Draw your UI and react to events that come in.  Of course there are somethings you want to happen without user interaction (spawning enemies, moving objects, scrolling backgrounds) that you will use a looping concept for, but it’s still a frames per second based event loop that does that work.

So if a timer doesn’t make sense for you, you can always setup a an enterFrame event (the frame per second event generator) and use system.getTimer() to determine if a millisecond amount of time has elapsed since the last enterFrame event and have your app react accordingly.

**untested code**

local lastTimerCheck = 0 local frequency = 200 local function enterFrameListener( event )       local now = event.time       if now \> (frequency + lastTimerCheck) then           lastTimerCheck = now           taskToDo()  -- your function to execute       end end Runtime:addEventListener( "enterFrame", enterFrameListener )

Rob

emm…UI will not respond. If I use sleep and busy waiting, I am worried about this. I don’t want this delay to affect UI’s response. Timer.performWithDelay (5000, function () native.requestExit () end) This function, I want the delay mechanism of this function to be encapsulated into a single delay. Repeat Dosomething Msleep (200) Until dosomethingisok I don’t know how much time it takes for dosomething, but I need to do it through this, and I can do the following. You just don’t do it for me.

  1. Can you please start posting full sentences and paragraphs.  Your posts are hard to read.

  2. We’ve been warning you. DO NOT use busy-loops or msleep().  This is why.  It will lock up your app and make it unusable.

From the way you describe the work, you need to use co-routines.  That said, there has to be a better way to structure your code so you can use timer.performWithDelay() and a task launching/execution system.

3.  Again, you’re not giving us a concrete usage example.  I can guess all day at a solution to a vague hypothetical problem, but it may not be what you’re trying to do at all.

What is the ‘real world’ usage of this work, sleep, work, sleep cycle.  What is the ‘work’.

As an example of one concrete problem and solution, see this tutorial: 

https://coronalabs.com/blog/2015/05/12/tutorial-responsive-real-time-searching/

Code: https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2015/05/responsiveSearches/code.zip

In a nutshell, as you type in letters, the app needs to find all words in a long list of words that match.  

It could do this in a blocking loop, but then the app would become non-responsive. 

So, instead, the app uses enterFrame and some basic rules to spread the search out over multiple frames.

Again, this is just one example of breaking up a long task with small waits between the work.

There is no use case to block the main thread.  If you think you need to do this then you need to rethink how you are structuring your code.  You’ve already had great help but if you need some lower level help then I’m sure @roaminggamer has options for you.

Sorry my English is bad. I know I can’t block the main thread. I just want a similar:

Timer.performWithDelay (5000, function () print (“hello1”) end)
Print (“hello2”)

5000 like these internal timers , used to perform some special usage judgements.
The above example will output: hello2, then wait for 5 seconds to output hello1, and will not block the main thread. I want a timer like this.

I am sure everyone here would like to help you, but I don’t think anyone is clear on what exactly it is that you need. In your last post, you gave an example of using the timer.performWithDelay, correctly identified how it would execute, and then said you want “a timer like this”. Why not just use the code you posted?

@Rob answered your initial question pretty directly, and in case it wasn’t clear, taskToDo() would either be a function containing your conditional logic or could simply be replaced by your conditional logic if you didn’t want to make another function. I have added to Rob’s code below to specifically fit what you were asking, including your n  variable.

local n=0 local lastTimerCheck = 0 local frequency = 200 local function doSomethingOnce() --This will execute once when n==1 print("n is now 1") end local function doSomethingUntil() --This will execute every 200 milliseconds until n==1 print("n is still 0") end local function enterFrameListener( event ) local now = event.time if now \> (frequency + lastTimerCheck) then lastTimerCheck = now if n==1 then Runtime:removeEventListener("enterFrame", enterFrameListener) doSomethingOnce() else doSomethingUntil() end end end Runtime:addEventListener( "enterFrame", enterFrameListener ) --Simulate n becoming 1 after an arbitrary amount of time timer.performWithDelay( 5500, function() n=1 end, 1)

 
 
There is no solution under the sun or moon  (pun intended) that will allow you to write code exactly like this and have it be non-blocking.  

do something wait do something wait ... do something wait

What you really need to do here is:

  1. Understand clearly the problem you are trying to solve (which is not how to write code like the above; that is not the task/work/problem.)

  2. Then, use the tools available to you to solve the problem.

 
The tools you have are:

While this is a very interesting problem, I must admit I cannot help you till you describe in clear detail what you are doing.

So far, you’ve given general description after general description, focusing entirely on the fact that you want to be able to code non-blocking blocking code.  i.e. Impossible code.

Please tell us the problem this code is supposed to solve.  i.e. Tell us what you game or app is doing with this code.  Then, and only then can we hope to be able to offer a solution that will fit your needs.

Corona and Lua are super-flexible so I guarantee the problem can be solved, whatever it is.  We just need to know.

Just for completeness, I want to point out that SSK2integrates starcrunch’s coroutine based Wait solution:

https://roaminggamer.github.io/RGDocs/pages/SSK2/external/#wait-starcrunch

So, in practice you could do this:

timer.performWithDelay(1, coroutine.wrap( function(event) local source = event.source -- DO THIS ssk.wait.ms( 500 ) print("1") ssk.wait.ms( 500 ) print("2") ssk.wait.ms( 500 ) print("3") timer.cancel(source) -- DO THIS end), 0)

In case anyone is confused, my last post is not what he is asking for, or at least what the pseudo-code we’ve seen so far is representing.

I say this because I am SURE he expects the last line of his pseudo code to block any subsequent code.

The code I posted simply enables waiting for the block in the call, not any code after that. 

So, any code after that block executes immediately.

I think, perhaps this is the closest I want, in the website mentioned above:

https://roaminggamer.github.io/RGDocs/pages/SSK2/external/

I wrote an example:

require “ssk2.loadSSK”
_G.ssk.init()
local initdata = { useExternal=true}
ssk.init(initdata)

timer.performWithDelay(20,
coroutine.wrap(
function(event)
local source = event.source – GOTCHA: save this now!
ssk.wait.ms( 1000 )
a = 11
b = 0
repeat
b = b + 1
ssk.wait.ms( 1000 )
print(b)
until b == 3

timer.cancel(source)
sss()
end), 0)

function sss()
print("---------------------------")
end

I am in China, our country no one uses (perhaps especially few, I did not see) corona SDK, I can get very little related information, my English is not good, I use translation software to understand communication, a lot of questions can only be asked in this forum, thank you for the warm help, thanks very much.

Hi.  I do not know how to help any more here.  I really do not understand why you need this and so I cannot give a useful answer.

As far as users in China goes,  I am sure there are many of Corona developers in China. 

However, I understand that you may be having issues with docs and translation.

Do Not Use Non-Corona Timers

Do not use msleep()

Do Not Write Blocking Code

Do not write code like this or you will block the app and hang it. 

for i = 1, 1000000000000, do -- busy loop; blocks progress. end print("done")

Corona is single threaded and waits till your Lua scripts complete to continue.

Use Corona Timers (performWithDelay)
You need to user timers to delay an action:
https://docs.coronalabs.com/api/library/timer/index.html
https://docs.coronalabs.com/api/library/timer/performWithDelay.html

local function doit() print( "Current sim time: ", system.getTimer() ) end doit() doit() -- function reference passed directly timer.performWithDelay( 1000, doit ) -- closure used to call function timer.performWithDelay( 2000, function() doit() end ) -- closure used to delay execute arbitrary code timer.performWithDelay( 2500, function() print( "Current sim time: ", system.getTimer() ) end )

co-routines
Alternately, you need to use coroutines to suspend a section of code and resume it later.
 
https://www.lua.org/pil/9.1.html
 
I’m not showing how to do this.  I don’t actually suggest it and it isn’t immediately clear how it works.  i.e. It takes some study.