lua-users home
lua-l archive

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


Hello all,

At work, we've been researching different options for working with an
asynchronous  multi-threaded API. Lua code is acting as a hardware
adaptor layer and eventually there will be N applications accessing N
C APIs, for which we are building a relatively standard Lua interface
to.

We've been studying the list and other resources and we are now
implementing a strategy, which, so far, seems to work. I'd like to
post an outline of it here, in order to get any comments that anyone
might be willing post.

The workflow:

1: Instantiate C-Side objects from Lua. These objects receive a
time-stamped "command" object (table) from Lua, which are their
execution instructions.
2: Callbacks may be embedded into any command object and when that
command is processed (at the supplied time stamp), the callback is
fired with the event's output as arguments.
3: Upon receiving an embedded callback, a new Lua thread is created
and anchored.
4: When the event fires, the callback is called or resumed (haven't
decided for sure if we need or should use coroutines here).
5: The callback's output is copied to a queue, which is either
referenced in an upvalue of the callback, or is part of its structure
(the callback is a functable).
6: This queue is protected by a mutex object, written in C. Here is an
overly-simple view of how it works:

self.lock = true
self[#self + 1] = new_status_return
self.lock = false

7: The main thread then picks values off of the cue and then
dispatches them to the application interface.

----

So far, "things aren't crashing." The callbacks are in their own
threads, Lua and OS, and they are running concurrently with the main
thread. The locks seem to be doing their job, because without them, we
eventually crash out. Also, the callbacks are simple so that they
don't hit too many Lua internals.

Here are some assumptions that we are making:

1: Unless we define `lua_lock` / `lua_unlock`, we need a mutex for
every shared access point, even for basic types, like numbers.
2: In these callback threads, if we stay away from shared access we
can do anything that we want, except possibly os.time / os.date and
the other functions that the Reference Manual says might not be thread
safe.

Most importantly, we're hoping that:

3: This is a well-worn path and that other people use this strategy,
quite regularly.
4: There is no clearly better alternative for our use case.

Thanks  in advance for any wisdom!

-Andrew