LuaThread
Multi-(platform|threading) support for the Lua language

home · installation · examples · reference


Examples

Below are some simple examples of multi-threaded Lua scripts. As people send me more nice examples, I will add them to this page. It would be interesting to have solutions to the basic IPC problems available here.

As simple as it gets

This simple program uses two independent threads of execution to flood the terminal with the words "parent" and "child", separated by commas.

local function flood(output, word)
    while 1 do 
        output:lock()
        io.write(word, ", ")
        output:unlock()
    end
end

local output = thread.newmutex()
thread.newthread(flood, {output, "child"})
flood(output, "parent")

A snippet the output could look like the text below:

parent, parent, parent, child, child, child, parent, child, child, child,
parent, parent, child, child, child, parent, parent, parent, child, child,
parent, parent, child, child, parent, parent, parent, child, parent, ...

Note that if the output mutex was not in use, the result could have included an output such as the following:

parent,  parentchild,  ,  parent, child,  child,  child,  parent,
child, child,  child, parent, parent, childparent,  child, child,
parent,  parent, parent,  child,  child, parent,  parent, child,  child,
parent, parent, parent, child, parent, ... 

That is because between writing the word and the comma, each thread could be preempted and control could be handed to the other thread. This is what the output mutex prevents.

Producer-consumer

Below is a program solving the classic producer-consumer problem. The code uses a the thread.queue module, which encapsulates all the synchronization:

SIZE = 128

local thread = require("thread")
local queue = require("thread.queue")

local fifo = queue.newqueue(SIZE)
local output = thread.newmutex()

function newcount()
    local mutex = thread.newmutex()
    local value = 1
    return function ()
        mutex:lock()
        local v = value
        value = value + 1
        mutex:unlock()
        return v
    end
end

local count = newcount()

function consumer(fifo, output)
    while 1 do
        local value = fifo:remove()
        output:lock()
        io.write("consumer removed ", value, "\n")
        output:unlock()
    end
end

function producer(count, fifo, output)
    while 1 do
        local value = count()
        fifo:insert(value)
        output:lock()
        io.write("producer inserted ", value, "\n")
        output:unlock()
    end
end

-- run consumer function in a new thread
thread.newthread(consumer, {fifo, output})

-- run producer function in the main thread
producer(count, fifo, output)

In summary, the consumer thread loops removing elements from the queue, while the producer thread loops inserting elements. When the queue is empty, the consumer is blocked by the queue until there are more elements available (i.e., until the producer threads inserts a new element). When the queue is full, the producer is blocked by the queue until there is a free slot (i.e., until the consumer removes an element).