Lua supports coroutines, also called collaborative multithreading. A coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends its execution by explicitly calling a yield function.
You create a coroutine by calling
coroutine.create. Its sole argument is a function that is the main function of the coroutine. The
create function only creates a new coroutine and returns a handle to it (an object of type thread); it does not start the coroutine.
You execute a coroutine by calling
coroutine.resume. When you first call
coroutine.resume, passing as its first argument a thread returned by
coroutine.create, the coroutine starts its execution by calling its main function. Extra arguments passed to
coroutine.resume are passed as arguments to that function. After the coroutine starts running, it runs until it terminates or yields.
A coroutine can terminate its execution in two ways: normally, when its main function returns (explicitly or implicitly, after the last instruction); and abnormally, if there is an unprotected error. In case of normal termination,
coroutine.resume returns true, plus any values returned by the coroutine main function. In case of errors,
coroutine.resume returns false plus the error object. In this case, the coroutine does not unwind its stack, so that it is possible to inspect it after the error with the debug API.
A coroutine yields by calling
coroutine.yield. When a coroutine yields, the corresponding
coroutine.resume returns immediately, even if the yield happens inside nested function calls (that is, not in the main function, but in a function directly or indirectly called by the main function). In the case of a yield,
coroutine.resume also returns true, plus any values passed to
coroutine.yield. The next time you resume the same coroutine, it continues its execution from the point where it yielded, with the call to
coroutine.yield returning any extra arguments passed to
coroutine.wrap function also creates a coroutine, but instead of returning the coroutine itself, it returns a function that, when called, resumes the coroutine. Any arguments passed to this function go as extra arguments to
coroutine.wrap returns all the values returned by
coroutine.resume, except the first one (the boolean error code). Unlike
coroutine.resume, the function created by
coroutine.wrap propagates any error to the caller. In this case, the function also closes the coroutine (see
As an example of how coroutines work, consider the following code:
function foo (a) print("foo", a) return coroutine.yield(2*a) end co = coroutine.create(function (a,b) print("co-body", a, b) local r = foo(a+1) print("co-body", r) local r, s = coroutine.yield(a+b, a-b) print("co-body", r, s) return b, "end" end) print("main", coroutine.resume(co, 1, 10)) print("main", coroutine.resume(co, "r")) print("main", coroutine.resume(co, "x", "y")) print("main", coroutine.resume(co, "x", "y"))
When you run it, it produces the following output:
co-body 1 10 foo 2 main true 4 co-body r main true 11 -9 co-body x y main true 10 end main false cannot resume dead coroutine