Garry's Mod Wiki

Concepts - Coroutines

Coroutines Vs Threads

Lua is not multi-threaded.

However, we emulate a multi-threaded behavior using coroutines. A coroutine is like a thread, as in it has its own execution flow. coroutines work in a cooperative nature, meaning while only one can execute at a time we are able to pause these "threads" during execution to allow other to run.

threads are what is returned by the creation of a coroutine in lua. These have no properties or member functions, but the thread objects are passed to coroutine.resume to tell which coroutine to start executing again.

Basics

Lua provides coroutine functionality through the coroutine table. You can create a coroutine using coroutine.create, which takes a function as its argument. It returns a value of type thread, representing the new coroutine:

co = coroutine.create( function() print( "hi" ) end ) print( co ) --> thread: 0x8071d98

When a coroutine is created, it starts in the suspended state:

print( coroutine.status(co) ) --> suspended

To start (or resume) a coroutine, use coroutine.resume. This changes its state from suspended to running:

coroutine.resume(co) --> hi

After it finishes running, its state becomes dead:

print( coroutine.status(co) ) --> dead

Yielding

Coroutines become useful with coroutine.yield, which pauses their execution and allows them to be resumed later.

co = coroutine.create( function() for i = 1, 10 do print( "co", i ) coroutine.yield() end end)

Now, resuming the coroutine steps through it one iteration at a time:

coroutine.resume(co) --> co 1 print( coroutine.status(co) ) --> suspended coroutine.resume(co) --> co 2 coroutine.resume(co) --> co 3 -- ... coroutine.resume(co) --> co 10 coroutine.resume(co) -- does nothing (coroutine is now dead)

Trying to resume a dead coroutine results in an error:

print( coroutine.resume(co) ) -- Output: false cannot resume dead coroutine

Passing Values Between resume and yield

Coroutines can exchange data with the code resuming them:

Pass arguments into the coroutine:

co = coroutine.create( function(a, b, c) print( "co", a, b, c ) end) coroutine.resume( co, 1, 2, 3 ) --> co 1 2 3

Get return values from yield:

co = coroutine.create( function(a, b) coroutine.yield( a + b, a - b ) end) print( coroutine.resume(co, 20, 10) ) --> true 30 10

Send values into a suspended coroutine:

co = coroutine.create( function() print( "co", coroutine.yield() ) end) coroutine.resume(co) -- starts, hits yield coroutine.resume(co, 4, 5) --> co 4 5

Return values from the coroutine function:

co = coroutine.create( function() return 6, 7 end) print( coroutine.resume(co) ) --> true 6 7

Additional Resources

Lua Wiki Coroutines Tutorial

Online Lua Manual Coroutines Chapter