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)