lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



I would see your case being okay using either mechanism.

In general, coroutines are faster and always portable (since they require no OS side support). It comes to how much isolation / synchronization you wish to have between the states. Coroutines have low isolation, high synchronization). Real OS threading has high isolation, low synchronization (varies by the toolkits).

One issue to keep in mind is multicore support. Coroutines always burden just a single core. OS threading will be balanced on all available cores.

Below is my ever-changing map of the Lua multithreading solutions (included in Lua Lanes manual).

-asko


==================
  Lua coroutines    (by Lua authors)
==================

http://www.lua.org/manual/5.1/manual.html#2.11
http://lua-users.org/wiki/CoroutinesTutorial

Lua coroutines is an integral part of Lua 5 itself. It is listed here, since it should be the _first_ multitasking mechanism to consider. It can also be used together with Lanes, or the other mechanisms listed below.

Coroutines are very usable in provider/consumer situations, allowing you to queue Lua functions on an as-needed dataflow basis with each other. Pros:
    - works with plain Lua (no extensions)
    - works on any platform
- lightweight (no OS level threading or locking involved)

Cons:
- co-operative, meaning your code will need to decide, who gets to run
    - does not utilize multiple CPUs/cores


=============
  LuaThread     (by Diego Nehab)
=============

http://www.cs.princeton.edu/~diego/professional/luathread/

LuaThread provides thread creation, mutexes, condition variables, and inter- thread queues to the Lua scripts. It takes a C-kind of approach, where Lua globals are shared by the threads running, and need therefore to be guarded
against multithreading conflicts.

Whether this is exactly what you want, or whether a more loosely implemented multithreading (s.a. Lanes) would be better, is up to you. One can argue that a loose implementation is easier for the developer, since no application level
lockings need to be considered.

Pros:
- no marshalling (data serialization) overhead, since threads share the
      same Lua state

Cons:
- requires a modified Lua core (not available as a module)
    - application level locking required
- Lua 5.0 and "before release of 5.1" mentioned (docs not updated for 5.1)

Sample:
<<
  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")
<<


=============
Lua Rings (by Roberto Ierusalimschy & Tomás Guisasola)
=============

http://www.keplerproject.org/rings/

".. library which provides a way to create new Lua states from within Lua. It also offers a simple way to communicate between the creator (master) and
the created (slave) states."

".. master can execute code in any of its slaves but each slave only has
access to its master (or its own slaves)."

Rings offers separate Lua states, but no multithreading. This makes it simple, but it won't use more than one CPU core. Other differences include:

    - opens all Lua standard libraries for subthreads
      (Lanes opens the needed ones)

    - marshalls numbers, strings, booleans, userdata
      (Lanes marshalls also tables, but not userdata)

- "remotedostring" allows executing code in the master state (Lanes does _not_ allow subthreads to trouble/modify master automatically, to allow effective sandboxing. The same can be achieved by sending code over (send/receive) between the threads, but master needs to explicitly
      do this)

- offers "Stable, a very simple API to manage a shared table at the master
      state"
(Lanes does not offer any shared data mechanisms, by design. They can be implemented using queues (send/receive) and a coroutine at the master
      end)

Pros:
- "offers Stable, a very simple API to manage a shared table at the master
    state"

Cons:
- thread contents defined as strings, not Lua source as such; does not give syntax check at file parsing, does not allow syntax highlight - Lua 5.0 mentioned (will be upcoming for 5.1 - right?)

Sample:
<<
  require"rings"
  S = rings.new ()

  data = { 12, 13, 14, }
  print (S:dostring ([[
  aux = {}
  for i, v in ipairs (arg) do
	table.insert (aux, 1, v)
  end
return unpack (aux)]], unpack (data))) -- true, 14, 13, 12

  S:close ()
<<


==========================
  Helper Threads Toolkit    (by Javier Guerra G.)
==========================

http://luaforge.net/projects/helper-threads/

"Provides a consistent framework to write non-blocking C libraries, with a Lua interface for starting tasks and managing the Futures, Queues and Threads."

This seems like a companion of the "occasional threading" model (see below); Lua side is kept clear of multithreading, while C side can be "spawn" off to
do things on the background.

Pros:
- provides an "update" mechanism, allowing the (C) thread and controlling
      Lua to interact during execution of the thread
    - ...

Cons:
- thread is "only for C code and it can't touch or access the Lua state", in other words there is no Lua-side multithreading concept (by design)


========================
  Occasional threading      (by Russ Cox)
========================

http://lua-users.org/lists/lua-l/2006-11/msg00368.html

".. able to have certain C calls run in parallel with the [Lua] VM, but
otherwise keep the VM single-threaded."

That pretty much says it all.

Pros:
- simple, yet providing for the "occasional" need to run really multithreaded - can be made into a loadable module (says the message)

Cons:
- only for occasional usage, the programming paradigm is still essentially
      singlethreaded (by definition)
- not a real project, just a message on the Lua list (but a good one!)


=============
  Lua Lanes
=============

Lua Lanes takes a loose approach, keeping each created Lua state completely separate from the others. Parameters, return values and globals (optionally) are passed transparently marshalled (serialized) between the threads.

Pros:
    - regular Lua 5.1 module
    - completely separate Lua states, one per thread
- very easy programming model, no application level locking - scales well, up to 1000's of threads (and any number of CPU cores)
    - provides priorities (-2..+2) for launched threads
    - asynchronous queues between M->S and S->M
    - threads are cancellable (with complete cleanup)
    - timeouts on all pending operations
- thread contents are given as regular (Master side) Lua functions; syntax checked early on, syntax highlighting works (thread contents
      can also be given in separate source files)
- standard libraries opened to the subthreads can be granually decided - automatic storage of a cancelled thread's globals, for "resurrectable"
      threads
- serializes calls to 'require', allowing wide compatibility with existing
      modules (and all, with minor changes)

Cons:
- marshalling data exchange may be a bottleneck for huge amounts, in which case use of filesystem for the bulk data may be better - userdata and functions not marshallable in send/receive - no shared access to data (can be implemented on top of the provided features)
    - ...



On Fri, 16 May 2008 16:56:38 +0800
 "Pete Kay" <petedao@gmail.com> wrote:
Hi,

I am working on an application that connects to a server through TCP/IP socket and listen for events continuously. When a certain event is picked
up, the application should performance some tasks.

What I want to do is to use Lua socket to listen for the events and then create a new thread each time a particular event type is received.

I found that there are two ways to do it, one is using coroutine and the
other one is to install Lua Thread.

It seems like they are very similar but I don't quite understand when it is
better to us coroutine or LuaThread.

Could someone give me some suggestions?

Thanks,
Pete