Garry's Mod Wiki

Revision Difference

thread#564743

<cat>Dev.Lua</cat> <title>Concepts - Threads</title>⤶ ⤶ Threads in Lua are returned by the <page>coroutine.create</page> function. They have no properties or member functions, and are used by the <page>coroutine.resume</page> function.⤶ ⤶ Be aware that coroutines are not multi-threading in the traditional sense. Coroutines are not run in parallel. See [here](http://lua-users.org/wiki/CoroutinesTutorial) for more information on Lua coroutines. ⤶ Read the [chapter on coroutines in the Lua online manual](https://www.lua.org/pil/9.html) for some examples <title>Concepts - Coroutines</title>⤶ ⤶ # Coroutines Vs Threads⤶ _**Lua is not multi-threaded**_. ⤶ However, we emulate a multi-threaded behavior using <page>coroutine</page>s. 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 <page>coroutine.resume</page> to tell which coroutine to start executing again.⤶ ⤶ ⤶ # Basics⤶ Lua provides coroutine functionality through the coroutine table. You can create a coroutine using <page>coroutine.create</page>, which takes a function as its argument. It returns a value of type thread, representing the new coroutine:⤶ ⤶ ```lua⤶ co = coroutine.create( function()⤶ print( "hi" )⤶ end )⤶ ⤶ print( co ) --> thread: 0x8071d98⤶ ⤶ ```⤶ ⤶ When a coroutine is created, it starts in the suspended state:⤶ ⤶ ```lua⤶ print( coroutine.status(co) ) --> suspended⤶ ```⤶ ⤶ To start (or resume) a coroutine, use <page>coroutine.resume</page>. This changes its state from suspended to running:⤶ ```lua⤶ coroutine.resume(co) --> hi⤶ ```⤶ After it finishes running, its state becomes dead:⤶ ```lua⤶ print( coroutine.status(co) ) --> dead⤶ ```⤶ ⤶ ## Yielding⤶ Coroutines become useful with <page>coroutine.yield</page>, which pauses their execution and allows them to be resumed later.⤶ ```lua⤶ 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:⤶ ```lua⤶ 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:⤶ ```lua⤶ 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:⤶ ```lua⤶ 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:⤶ ```lua⤶ 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:⤶ ```lua⤶ 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:⤶ ```lua⤶ co = coroutine.create( function()⤶ return 6, 7⤶ end)⤶ ⤶ print( coroutine.resume(co) ) --> true 6 7⤶ ```⤶ ⤶ # Additional Resources⤶ ⤶ [Lua Wiki Coroutines Tutorial](http://lua-users.org/wiki/CoroutinesTutorial)⤶ ⤶ [Online Lua Manual Coroutines Chapter](https://www.lua.org/pil/9.html)