Lua - Coroutine Control Flow



Lua Coroutines provides a unique way to control their flow by allowing to pause and resume their execution during application run in a non-preemptive manner. We can simulate concurrency, and can structure complex workflows. Following are the methods which governs control flow of coroutines in Lua.

coroutine.create(f) function

  • A coroutine is defined using coroutine.create(f) function. It acts as a starting point for coroutines. f is the implementation of the coroutine.

  • coroutine.create(f) creates the coroutine, but it is not started.

  • This function returns an object of type Thread representing the coroutine.

coroutine.resume(co,...) function

  • A coroutine co is started or resumed using coroutine.resume(co,...) function. If resume is called first time, thread is started earlier created using coroutine.resume(co,...) accepts arguments which eventually are passed to coroutine function.

  • coroutine.resume(co,...) returns status as either true if call is successful otherwise false.

  • If status is true, resume() function returns the value passed to yield() function. Otherwise, it will return an error message.

coroutine.yield(...) function

  • Current coroutine is paused or suspended using coroutine.yield(...) function. This function returns arguments passed to coroutine.yield(...) function to the caller function which resume it using coroutine.resume(co,...) function.

  • coroutine.resume(co,...) returns status as either true if call is successful otherwise false.

  • A coroutine state as value of local variables and point of execution are preserved.

  • A coroutine co remains suspended until resumed by coroutine.resume(co,...) function.

coroutine.status(co) function

coroutine.status(co) returns the current state of the coroutine as a string. Following are possible states of a coroutine.

  • running signifies the coroutine is currently in running state.

  • suspended signifies that the coroutine is either created or is in suspended by yield() call.

  • normal signifies the coroutine is active but not in running state.

  • dead signifies the coroutine has finished its execution or faced error.

coroutine.wrap(f) function

  • coroutine.wrap(f) returns a wrapper over coroutine and is used to provide high level scenarios like creating a iterator.

  • It takes f as function and returns a new function. Whenver this function is called, coroutine is resumed and returns the value yielded by the coroutine.

  • In case no value is yielded, wrapper function returns nothing. In case of error in coroutine execution, wrapper function receives the error.

Example - Using states of Coroutine

main.lua

function coroutine1()
   print("Coroutine started")
   local value1 = coroutine.yield(10)
   print("Coroutine resumed, received:", value1)
   local value2 = coroutine.yield(value1 * 2)
   print("Coroutine finished")
   local value2 = coroutine.yield(value2 + 5)
   return value2 + 5
end

co = coroutine.create(coroutine1)

status, yield1 = coroutine.resume(co)
-- prints Main thread:	true	10
print("Main thread:", status, yield1)

status, yield2 = coroutine.resume(co, yield1)
-- Main thread:	true	20
print("Main thread:", status, yield2) 

status, result = coroutine.resume(co, yield2)

-- Main thread:	true	25
print("Main thread:", status, result) 

-- Coroutine status:	suspended
print("Coroutine status:", coroutine.status(co))   -- Output: dead 

Output

When we run the above code, we will get the following output−

Coroutine started
Main thread:	true	10
Coroutine resumed, received:	10
Main thread:	true	20
Coroutine finished
Main thread:	true	25
Coroutine status:	suspended
Advertisements