Has Lua got threads?
Yes and no, depending on the meaning of 'threads'. If you mean multitasking with OS threads, the answer is no, but Lua has coroutines which allow cooperative multitasking. A coroutine is a function which may yield at any point and may be resumed later. While it is yielded, it keeps its state, no matter how deep the call stack.
Since coroutines may be unfamiliar to most people, a little example:
local yield = coroutine.yield function cofun()
yield(10)
yield(20)
yield(30)
end fun = coroutine.wrap(cofun)
print(fun())
print(fun())
print(fun())
=>
10
20
30
A powerful use of coroutines is to write iterators. It is often easy to express things such as tree traversal recursively, and using coroutines makes it almost trivial to wrap this as an iterator: yield
can be called from any function called from a coroutine.
This does an 'in order' traversal of a tree data structure:
function tree(t)
if t.left then tree(t.left) end
yield (t.value)
if t.right then tree(t.right) end end function tree_iter(t)
return coroutine.wrap(function() return tree(t) end)
end t = {
value = 10,
left = {
value = 20
},
right = {
value = 30
}
}
for v in tree_iter(t) do
print(v)
end
=>
20
10
30
The for
statement is expecting a function of no arguments, which it will call repeatedly until nil
is returned. iter
wraps a function of no arguments which calls tree
with the given tree table and returns it - an example of using a closure.
Copas uses coroutines in a particularly elegant way to allow the construction of network servers. The theory is nicely explained here in Programming In Lua.
-- Run the test file and the connect to the server using telnet on the used port.
-- The server should be able to echo any input, to stop the test just send the command "quit"
require "copas"
local function echoHandler(skt)
skt = copas.wrap(skt)
while true do
local data = skt:receive()
if data == "quit" then
break
end
skt:send(data)
end end local server = socket.bind("localhost", 20000)
copas.addserver(server, echoHandler)
copas.loop()
Note that this example can handle a number of simultaneous connections, since Copas schedules the various sessions using coroutines. This is usually done using OS threads or ugly calls to select()
.
There are libraries which take Lua beyond coroutines. True OS threads have been added to Lua with LuaThread, although this does require patching the source. Note that this can be inefficient due to the amount of locking required.
An efficient way to run multiple Lua states in parallel is provided by Lanes. These separate states are called 'lanes' and they do not share data, instead communicating with each with linda objects that act as channels.
A good overview of multitasking and concurrency in Lua is here, plus some comparisons
As for Lua and threading with C extensions, an introduction is given here and discussed further here. In particular, Lua coroutines can be safely driven from a different OS thread in a C extension.