Communication between threads can be tedious to get right. With a ZeroMQ library, you can easily reuse the previous code to move from the network to interprocess communication merely by changing the transport protocol in the connection string. The LuaZMQ library incorporates simple thread control capabilities but you're free to use any libraries to manage threads.
Note that the Lua language contains coroutines to achieve cooperative multitasking, except that everything is processed in a single thread relying on explicit scheduling. It means that only one CPU core is used by your application.
This recipe will give you basic insight in to parallel processing of information in the Lua language.
You'll be sending the well known filling text Lorem ipsum
to the reply side and it'll append dolor sit amet
in the end. The resulting text will be sent back to the request side and displayed on the screen.
You can view this recipe as a simple mashup of the request-reply model into one Lua script, while the request part is processed in parallel to the reply part.
In this case, the whole thread code for the request part will be stored in a string variable that will be processed in another thread:
local req = [[ local name = unpack(arg) local socket,msg = assert(context.socket(zmq.ZMQ_REQ)) local result, msg = assert(socket.connect("inproc://test1")) local poll = zmq.poll() poll.add(socket, zmq.ZMQ_POLLIN, function(socket) local result = socket.recvAll() if result then print(name, string.format("Recieved data: %q", result)) end end) socket.send("Lorem ipsum") poll.start() socket.close() ]]
As you can see, there's not a single line that would explicitly say that this code will be processed in a thread.
local zmq = require 'zmq' local context, msg = assert(zmq.context()) local socket,msg = assert(context.socket(zmq.ZMQ_REP)) local result, msg = assert(socket.bind("inproc://test1")) local poll = zmq.poll() poll.add(socket, zmq.ZMQ_POLLIN, function(socket) local result = socket.recvAll() if result then print("Reply part", string.format("Recieved data: %q", result)) socket.send(result.." dolor sit amet") end end)
context.thread
function, which expects at least one parameter with the thread code in a single string. You can add another parameter that will be added into the thread global argument list.local thread = context.thread(req, 'Request part') poll.start()
Parent thread kills its children
. It sounds horrible as it's a sign of bad application design.thread.join() socket.close()
This recipe uses inproc
or in-process transport to communicate with the request-reply pattern. Almost every aspect of communication remains the same except that the ZeroMQ library uses the shared memory region to transfer messages between threads. This works exceptionally well even without tedious synchronization routines. By using the push-pull socket types instead of request-reply, you can easily create a distributed processing system with a few lines of code or even combine it with the pgm
transport protocol to achieve distributed computing on more than one computer.
Threads are created with the context.thread
function, where the first argument is always a thread code. LuaZMQ will create a new independent Lua state that shares only the context object. The context object is thread-safe; therefore, it can be shared among all threads.
Optionally, you can add numerical or string variables, which will be available to the thread code via the global arg
variable. This emulates a situation where you execute the Lua script with arguments.
The only tricky part is thread management. Before closing your main process, it should always wait for its threads to finish up using the thread.join
function.
13.59.197.213