You asked for - Coroutines
Disclaimer : I am not an expert in Lua myself and there are a lot of aspects that I need to familiarise myself with.
Now that we have that out of the way, Here's my understanding of co-routines and how they could be used.
What is a co-routineA co-routine is a thread but I found it to be different from being a thread. When you call a function, the return address is pushed to the stack, so that when the function is over the processing can return to where it branched off from. A co-routine is more like a function that can be interrupted and resumed. A co-routine is a way to split the execution of a function until a point and can then resume execution from that point onwards. Lua co-routines are not multi-threaded in the way threads are on PC/Mac, they are collaborative multi-tasking.
What are the co-routine functionsThe functions associated with co-routines are
coroutine.create - Creates a new coroutine thread coroutine.resume - Start or resume a thread coroutine.running - Returns the running coroutine coroutine.status - Returns the status of a thread coroutine.wrap - Creates a thread and returns a function to resume it coroutine.yield - Yields execution of thread back to the caller
How to use co-routinesStep 1. Create a new co-routine
local function f(a,b) print(a,b) end thread = coroutine.create (f) -- thread will run function f
Step 2. Return execution to the main thread
local function f(a) print("I have started this function with the value " .. a) v = coroutines.yield("Bummer") print("The value of v is now " .. v) return 2011 end thread = coroutines.create(f) _,result = coroutine.resume(thread,1900) -- This shall run the thread/start it up print(result) -- See what we got from yield _,result = coroutines.resume(thread,2000) print(result) -- See what the function returned
When a coroutines is called using yield(params), the arguments passed in yield are returned to the caller/main thread
When a coroutine is resumed using resume(thread, params) the parameters are passed as if they were passed to the function
Sometimes, in a context that I cannot put to words, you might have a co-routine running that might do several things and keep on being resumed/paused, etc you would want to know if the co-routines is running or suspended or dead, (let's say if you were responding to a event).
so status = coroutine.status(thread) will return one of the four states
so before you resume, you can check if it is suspended, only then resume it.
Closing wordsI am still trying to work out how they can be useful, In some cases where you want to do a complex long processing, one can have a series of yields and resumes in the function like
local function doLongProcessing(a) --Do processing 25% thread1 = coroutines.yield("25%") --> this can be used to update the screen somewhere --Do processing 50% thread1 = coroutines.yield("50%") --> this can be used to update the screen somewhere --Do processing 100% thread1 = coroutines.yield("100%") --> this can be used to update the screen somewhere --All done end
and of course you will also need to have in the main thread something like
thread = coroutine.create(f) while coroutine.status(thread) ~= "dead" do _,res = coroutine.resume(thread) --do something with the returned value print("Progress is " .. res) end
I shall add more samples and explanation as I figure out the usage of this myself. I was looking for something that was equivalent of DoEvents() from VB6 something that is a breather for the loops/main thread. If you were to run this code
local text = display.newText("",10,100,nil,14) for i=1,10000 do -- do nothing text.text = i end
you will find that the app gets blocked, on the simulator you see the wait animation (BeachBall), and when it responds, the text will display 10000, what I was after was that it should display every number that I has iterated through. Now coroutines will also not help us there, the only way to do this is by using the onEnterFrame, so I am forced to think on what is the better and more optimal way to get things done.
If you have an feedback, please feel free to post comments, if you post them anonymously, that's fine too, but if you put your name, I can attribute you for the same.