The luv project provides access to the multi-platform support library
libuv to lua code. It was primariliy developed for the luvit project as
the uv
builtin module, but can be used in other lua environments.
Here is a small example showing a TCP echo server:
local uv = require('uv')
local server = uv.new_tcp()
server:bind("127.0.0.1", 1337)
server:listen(128, function (err)
assert(not err, err)
local client = uv.new_tcp()
server:accept(client)
client:read_start(function (err, chunk)
assert(not err, err)
if chunk then
client:write(chunk)
else
client:shutdown()
client:close()
end
end)
end)
print("TCP server listening at 127.0.0.1 port 1337")
uv.run()
As a quick note, libuv is a C library and as such, there are no such things
as methods. The luv bindings allow calling the libuv functions as either
functions or methods. For example, calling server:bind(host, port)
is
equivalent to calling uv.tcp_bind(server, host, port)
. All wrapped uv types
in lua have method shortcuts where is makes sense. Some are even renamed
shorter like the tcp_
prefix that removed in method form. Under the hood it's
the exact same C function.
The rest of the docs are organized by libuv type. There is some hierarchy as most types are considered handles and some are considered streams.
uv_loop_t
— Event loopuv_handle_t
— Base handleuv_timer_t
— Timer handleuv_prepare_t
— Prepare handleuv_check_t
— Check handleuv_idle_t
— Idle handleuv_async_t
— Async handleuv_poll_t
— Poll handleuv_signal_t
— Signal handleuv_process_t
— Process handleuv_stream_t
— Stream handleuv_udp_t
— UDP handleuv_fs_event_t
— FS Event handleuv_fs_poll_t
— FS Poll handle
- Filesystem operations
- DNS utility functions
- Miscellaneous utilities
The event loop is the central part of libuv’s functionality. It takes care of polling for i/o and scheduling callbacks to be run based on different sources of events.
In luv, there is an implicit uv loop for every lua state that loads the library. You can use this library in an multithreaded environment as long as each thread has it's own lua state with corresponsding own uv loop.
Closes all internal loop resources. This function must only be called once the loop has finished its execution or it will raise a UV_EBUSY error.
optional
mode
defaults to"default"
This function runs the event loop. It will act differently depending on the specified mode:
-
"default"
: Runs the event loop until there are no more active and referenced handles or requests. Always returnsfalse
. -
"once"
: Poll for i/o once. Note that this function blocks if there are no pending callbacks. Returnsfalse
when done (no active handles or requests left), ortrue
if more callbacks are expected (meaning you should run the event loop again sometime in the future). -
"nowait"
: Poll for i/o once but don’t block if there are no pending callbacks. Returnsfalse
if done (no active handles or requests left), ortrue
if more callbacks are expected (meaning you should run the event loop again sometime in the future).
Luvit will implicitly call uv.run()
after loading user code, but if you use
the luv
bindings directly, you need to call this after registering your
initial set of event callbacks to start the event loop.
Returns true if there are active handles or request in the loop.
Stop the event loop, causing uv_run()
to end as soon as possible. This
will happen not sooner than the next loop iteration. If this function was called
before blocking for i/o, the loop won’t block for i/o on this iteration.
Get backend file descriptor. Only kqueue, epoll and event ports are supported.
This can be used in conjunction with uv_run("nowait")
to poll in one thread
and run the event loop’s callbacks in another.
Note: Embedding a kqueue fd in another kqueue pollset doesn’t work on all platforms. It’s not an error to add the fd but it never generates events.
Get the poll timeout. The return value is in milliseconds, or -1 for no timeout.
Return the current timestamp in milliseconds. The timestamp is cached at the
start of the event loop tick, see uv.update_time()
for details and rationale.
The timestamp increases monotonically from some arbitrary point in time. Don’t make assumptions about the starting point, you will only get disappointed.
Note: Use
uv.hrtime()
if you need sub-millisecond granularity.
Update the event loop’s concept of “now”. Libuv caches the current time at the start of the event loop tick in order to reduce the number of time-related system calls.
You won’t normally need to call this function unless you have callbacks that block the event loop for longer periods of time, where “longer” is somewhat subjective but probably on the order of a millisecond or more.
Walk the list of handles: callback
will be executed with the handle.
-- Example usage of uv.walk to close all handles that aren't already closing.
uv.walk(function (handle)
if not handle:is_closing() then
handle:close()
end
end)
method form
handle:is_active()
method form
handle:is_closing()
method form
handle:close(callback)
method form
handle:ref()
method form
handle:unref()
method form
handle:has_ref()
method form
handle:send_buffer_size(size)
method form
handle:recv_buffer_size(size)
method form
handle:fileno()
Stream handles provide an abstraction of a duplex communication channel.
uv_stream_t
is an abstract type, libuv provides 3 stream implementations in
the form of uv_tcp_t
, uv_pipe_t
and uv_tty_t
.
(method form
stream:shutdown(callback) -> req
)
(method form
stream:listen(backlog, callback)
)
(method form
stream:accept(client_stream)
)
(method form
stream:read_start(callback)
)
(method form
stream:read_stop()
)
(method form
stream:write(data, callback)
)
(method form
stream:write2(data, handle, callback)
)
(method form
stream:try_write(data)
)
(method form
stream:is_readable()
)
(method form
stream:is_writable()
)
(method form
stream:set_blocking(blocking)
)
TCP handles are used to represent both TCP streams and servers.
uv_tcp_t
is a ‘subclass’ of uv_stream_t
.
(method form
tcp:open(sock)
)
(method form
tcp:nodelay(enable)
)
(method form
tcp:keepalive(enable)
)
(method form
tcp:simultaneous_accepts(enable)
)
(method form
tcp:bind(host, port)
)
(method form
tcp:getpeername()
)
(method form
tcp:getsockname()
)
(method form
tcp:connect(host, port, callback) -> req
)
(method form
tcp:write_queue_size() -> size
)
All handle types in the uv
module provide these base operations.
All handle types provided by the uv
module can be closed using the
close(handle, callback)
function or the <handle>:close(callback)
method.
The handle
argument specifies the handle to close. If using the close()
method this argument is omitted.
The optional callback
argument allows the user to provide a function to be
ran after the close operation completes.
The close()
function always returns nil
, it will raise an error if the
handle
specified is already being closed.
local uv = require('uv')
local socket = uv.new_tcp()
socket:close()
local uv = require('uv')
local socket = uv.new_pipe(false)
uv.close(socket, function() print("pipe closed") end)
Streaming handles are used to abstract duplex communication channels such as TCP Sockets, piping sockets and tty interfaces.
Streaming handles can be disconnected by using the shutdown(handle, callback)
function or the <streaming handle>:shutdown(callback)
method on streaming
handle objects.
The handle
argument specifies the handle to disconnect. If using the
shutdown()
method this argument is omitted.
The optional callback
argument allows the user to provide a function to be
ran after the shutdown operation completes.
shutdown()
returns the uv_shutdown_t
request associated with the underlying
shutdown operation.
The TCP handle type is used for both client and server TCP sockets.
The Streaming and UV Handle operations are available to TCP socket handles.
TCP sockets are created using the new_tcp()
function.
tcp_new()
will return a newly initialized TCP socket handle. A Lua error will
be thrown for initialization failures.
local uv = require('uv')
local tcp_handle = uv.new_tcp()
TCP sockets can be bound to ports via the
tcp_bind(tcp_handle, host, port, options)
function or the
<tcp_handle>:bind(host, port, options)
method.
The handle
argument is the initialized TCP socket to bind to the address. If
using the bind()
method on a tcp_handle object this argument is omitted.
The host
argument takes a string for the interface to bind on, it supports
IPv4 and IPv6 addresses.
The port
argument takes an integer to use as the port to bind on.
The options
argument is optional. It is a table that can be used to utilize
extra functionality for binding. Currently the only supported option is
ipv6only
, which if set will force binding using IPv6.
tcp_bind()
operations will return 0 for successful operations. A Lua error
will be thrown for binding failures.
local uv = require('uv')
local server = uv.new_tcp()
server:bind('127.0.0.1', 8080)
local uv = require('uv')
local server = uv.new_tcp()
uv.tcp_bind(server, '::1', 8080, {ipv6only=true})