Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are Lua coroutines even for? Why doesn't this code work as I expect it?

I'm having trouble understanding this code... I was expecting something similar to threading where I would get an output with random "nooo" and "yaaaay"s interspersed with each other as they both do the printing asynchronously, but rather I discovered that the main thread seems to block on the first calling of coroutine.resume() and thus prevents the next from being started until the first has yielded.

If this is the intended operation coroutines, what are they useful for, and how would I achieve the goal I was hoping for? Would I have to implement my own scheduler for these coroutines to operate asynchronously?, because that seems messy, and I may as well use functions!

co1 = coroutine.create(function ()         local i = 1         while i < 200 do                 print("nooo")                 i = i + 1         end         coroutine.yield() end)  co2 = coroutine.create(function ()         local i = 1         while i < 200 do                 print("yaaaay")                 i = i + 1         end         coroutine.yield() end)  coroutine.resume(co1) coroutine.resume(co2) 
like image 922
kellpossible Avatar asked Feb 26 '11 17:02

kellpossible


People also ask

What are Lua coroutines?

Coroutines are blocks of Lua code which are created within Lua, and have their own flow of control like threads. Only one coroutine ever runs at a time, and it runs until it activates another coroutine, or yields (returns to the coroutine that invoked it).

How are Lua coroutines implemented?

By implementing a coroutine as a separate stack, Lua al- lows calls to coroutine. yield to occur even from inside nested Lua functions (i.e., directly or indirectly called by the coroutine main function). The next time the coroutine is resumed, its execution will continue from the exact point where it suspended.

Is Lua coroutines multithreaded?

Lua coroutines provide cooperative multithreading, which is why they are called coroutines. They cooperate with each other. Only one thing runs at a time, and you only switch tasks when the tasks explicitly say to do so.


1 Answers

Coroutines aren't threads.

Coroutines are like threads that are never actively scheduled. So yes you are kinda correct that you would have to write you own scheduler to have both coroutines run simultaneously.

However you are missing the bigger picture when it comes to coroutines. Check out wikipedia's list of coroutine uses. Here is one concrete example that might guide you in the right direction.

    -- level script     -- a volcano erupts every 2 minutes     function level_with_volcano( interface )              while true do             wait(seconds(5))             start_eruption_volcano()             wait(frames(10))             s = play("rumble_sound")             wait( end_of(s) )             start_camera_shake()                     -- more stuff              wait(minutes(2))         end          end 

The above script could be written to run iteratively with a switch statement and some clever state variables. But it is much more clear when written as a coroutine. The above script could be a thread but do you really need to dedicate a kernel thread to this simple code. A busy game level could have 100's of these coroutines running without impacting performance. However if each of these were a thread you might get away with 20-30 before performance started to suffer.

A coroutine is meant to allow me to write code that stores state on the stack so that I can stop running it for a while (the wait functions) and start it again where I left off.

like image 59
deft_code Avatar answered Sep 23 '22 06:09

deft_code