ljuv is a module built on libuv and LuaJIT 2.1 (HEAD).
A main event loop combined with coroutines can be a way to nicely parallelize and synchronize various operations; one of the computing problems.
Not only a binding to libuv, the module aims to expose different levels of abstraction and address problems like multi-threading.
Install
See src/
, rockspecs/
or
luarocks.
Documentation
Note: When the documentation is very succinct because it is just a layer above the libuv API, refer to the libuv documentation.
Levels of abstraction
If the regular API is too high level, e.g. poor performance or some features are missing, the ljuv submodules may be directly used:
ljuv.libuv
: The FFI binding and library namespace of libuv (not exhaustive).ljuv.wrapper
: The ljuv C API, which is used to implement additional features like thread and channel.
Error handling
Callbacks
Errors from loop callbacks are properly handled; they will be deferred, queued and propagated by loop:run as soon as possible (with a call to loop:stop). After an error, the state of the loop is still valid and loop:run can be called again to propagate the next error or to continue execution.
Note: In most cases catching errors from loop:run, the root of the application, is not meaningful and it should probably be done at the callback level instead.
Resources management
Loop and handles
Handles are created and owned by a loop, they are not garbage collected on their own. To release an handle and its resources, handle:close must be called. A loop will close its handles when garbage collected.
Warning: Due to the design of ljuv, if an handle callback is an anchor for the associated loop, e.g. it has a reference to it directly or indirectly by its upvalues, the loop will not be garbage collected until the VM is closed. For most applications it will not matter because they will use the default global loop as their main event loop.
Although ljuv uses cdata objects, care is taken to preserve their identity in the API. When an handle is passed to a callback it will be the same cdata object created by the loop. That cdata object identifies the handle and can be used as a key.
Shared objects
Objects like channels or shared flags are properly managed from multiple threads by the use of reference counting (if correctly exported/imported).
An async handle exported to another thread will act more as a weak reference: the validity of the handle is checked before attempting an operation.
String buffers
ljuv uses LuaJIT's string buffers to pass data between threads. Look at the LuaJIT documentation to know about what kind of data is supported.