ghostty/pkg/libuv/Loop.zig
Mitchell Hashimoto b2192ea8f7 move libuv into pkg
2022-08-16 17:47:44 -07:00

124 lines
4.2 KiB
Zig
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const Loop = @This();
const std = @import("std");
const Allocator = std.mem.Allocator;
const testing = std.testing;
const c = @import("c.zig");
const errors = @import("error.zig");
loop: *c.uv_loop_t,
/// Initialize a new uv_loop.
pub fn init(alloc: Allocator) !Loop {
// The uv_loop_t type MUST be heap allocated and must not be copied.
// I can't find a definitive source on this, but the test suite starts
// hanging in weird places and doing bad things when it is copied.
const loop = try alloc.create(c.uv_loop_t);
try errors.convertError(c.uv_loop_init(loop));
return Loop{ .loop = loop };
}
/// Releases all internal loop resources. Call this function only when the
/// loop has finished executing and all open handles and requests have been
/// closed, or this will silently fail (in debug mode it will panic).
pub fn deinit(self: *Loop, alloc: Allocator) void {
// deinit functions idiomatically cannot fail in Zig, so we do the
// next best thing here and assert so that in debug mode you'll get
// a crash.
std.debug.assert(c.uv_loop_close(self.loop) >= 0);
alloc.destroy(self.loop);
self.* = undefined;
}
/// Returns true if the loop is still alive.
pub fn alive(self: Loop) !bool {
const res = c.uv_loop_alive(self.loop);
try errors.convertError(res);
return res > 0;
}
/// This function runs the event loop. See RunMode for mode documentation.
///
/// This is not reentrant. It must not be called from a callback.
pub fn run(self: Loop, mode: RunMode) !u32 {
const res = c.uv_run(self.loop, @enumToInt(mode));
try errors.convertError(res);
return @intCast(u32, res);
}
/// 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 wont block for i/o on this iteration.
pub fn stop(self: Loop) void {
c.uv_stop(self.loop);
}
/// Get backend file descriptor. Only kqueue, epoll and event ports are supported.
///
/// This can be used in conjunction with uv_run(loop, UV_RUN_NOWAIT) to poll
/// in one thread and run the event loops callbacks in another see
/// test/test-embed.c for an example.
pub fn backendFd(self: Loop) !c_int {
const res = c.uv_backend_fd(self.loop);
try errors.convertError(res);
return res;
}
/// Get the poll timeout. The return value is in milliseconds, or -1 for no
/// timeout.
pub fn backendTimeout(self: Loop) c_int {
return c.uv_backend_timeout(self.loop);
}
/// 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.
/// Dont make assumptions about the starting point, you will only get disappointed.
pub fn now(self: Loop) u64 {
return c.uv_now(self.loop);
}
/// Update the event loops 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 wont 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.
pub fn updateTime(self: Loop) void {
return c.uv_update_time(self.loop);
}
/// Sets loop->data to data.
pub fn setData(self: Loop, pointer: ?*anyopaque) void {
c.uv_loop_set_data(self.loop, pointer);
}
/// Returns loop->data.
pub fn getData(self: Loop, comptime DT: type) ?*DT {
return if (c.uv_loop_get_data(self.loop)) |ptr|
@ptrCast(?*DT, @alignCast(@alignOf(DT), ptr))
else
null;
}
/// Mode used to run the loop with uv_run().
pub const RunMode = enum(c.uv_run_mode) {
default = c.UV_RUN_DEFAULT,
once = c.UV_RUN_ONCE,
nowait = c.UV_RUN_NOWAIT,
};
test {
var loop = try init(testing.allocator);
defer loop.deinit(testing.allocator);
var data: u8 = 42;
loop.setData(&data);
try testing.expect(loop.getData(u8).?.* == 42);
try testing.expect((try loop.backendFd()) > 0);
try testing.expectEqual(@as(u32, 0), try loop.run(.nowait));
}