mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
use async handles to more immediately exit the event loop
This commit is contained in:
32
src/App.zig
32
src/App.zig
@ -55,7 +55,8 @@ pub fn deinit(self: *App) void {
|
|||||||
// Run the loop one more time, because destroying our other things
|
// Run the loop one more time, because destroying our other things
|
||||||
// like windows usually cancel all our event loop stuff and we need
|
// like windows usually cancel all our event loop stuff and we need
|
||||||
// one more run through to finalize all the closes.
|
// one more run through to finalize all the closes.
|
||||||
_ = self.loop.run(.default) catch unreachable;
|
_ = self.loop.run(.default) catch |err|
|
||||||
|
log.err("error finalizing event loop: {}", .{err});
|
||||||
|
|
||||||
// Dealloc our allocator copy
|
// Dealloc our allocator copy
|
||||||
self.alloc.destroy(self.loop.getData(Allocator).?);
|
self.alloc.destroy(self.loop.getData(Allocator).?);
|
||||||
@ -76,13 +77,11 @@ pub fn run(self: App) !void {
|
|||||||
defer embed.deinit(self.alloc);
|
defer embed.deinit(self.alloc);
|
||||||
try embed.start();
|
try embed.start();
|
||||||
|
|
||||||
// We need at least one handle in the event loop at all times so
|
// This async handle is used to "wake up" the embed thread so we can
|
||||||
// that the loop doesn't spin 100% CPU.
|
// exit immediately once the windows want to close.
|
||||||
var timer = try libuv.Timer.init(self.alloc, self.loop);
|
var async_h = try libuv.Async.init(self.alloc, self.loop, (struct {
|
||||||
errdefer timer.deinit(self.alloc);
|
fn callback(_: *libuv.Async) void {}
|
||||||
try timer.start((struct {
|
}).callback);
|
||||||
fn callback(_: *libuv.Timer) void {}
|
|
||||||
}).callback, 5000, 5000);
|
|
||||||
|
|
||||||
while (!self.window.shouldClose()) {
|
while (!self.window.shouldClose()) {
|
||||||
try self.window.run();
|
try self.window.run();
|
||||||
@ -95,14 +94,19 @@ pub fn run(self: App) !void {
|
|||||||
try embed.loopRun();
|
try embed.loopRun();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close our timer so that we can cleanly close the loop.
|
// Notify the embed thread to stop. We do this before we send on the
|
||||||
timer.close((struct {
|
// async handle so that when the thread goes around it exits.
|
||||||
fn callback(t: *libuv.Timer) void {
|
embed.stop();
|
||||||
const alloc = t.loop().getData(Allocator).?.*;
|
|
||||||
t.deinit(alloc);
|
// Wake up the event loop and schedule our close.
|
||||||
|
try async_h.send();
|
||||||
|
async_h.close((struct {
|
||||||
|
fn callback(h: *libuv.Async) void {
|
||||||
|
const alloc = h.loop().getData(Allocator).?.*;
|
||||||
|
h.deinit(alloc);
|
||||||
}
|
}
|
||||||
}).callback);
|
}).callback);
|
||||||
|
|
||||||
embed.stop();
|
// Wait for the thread to end which should be almost instant.
|
||||||
try embed.join();
|
try embed.join();
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,14 @@ handle: *c.uv_async_t,
|
|||||||
|
|
||||||
pub usingnamespace Handle(Async);
|
pub usingnamespace Handle(Async);
|
||||||
|
|
||||||
pub fn init(alloc: Allocator, loop: Loop, comptime cb: fn (Async) void) !Async {
|
pub fn init(alloc: Allocator, loop: Loop, comptime cb: fn (*Async) void) !Async {
|
||||||
var handle = try alloc.create(c.uv_async_t);
|
var handle = try alloc.create(c.uv_async_t);
|
||||||
errdefer alloc.destroy(handle);
|
errdefer alloc.destroy(handle);
|
||||||
|
|
||||||
const Wrapper = struct {
|
const Wrapper = struct {
|
||||||
pub fn callback(arg: [*c]c.uv_async_t) callconv(.C) void {
|
pub fn callback(arg: [*c]c.uv_async_t) callconv(.C) void {
|
||||||
const newSelf: Async = .{ .handle = arg };
|
var newSelf: Async = .{ .handle = arg };
|
||||||
@call(.{ .modifier = .always_inline }, cb, .{newSelf});
|
@call(.{ .modifier = .always_inline }, cb, .{&newSelf});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ test "Async" {
|
|||||||
var loop = try Loop.init(testing.allocator);
|
var loop = try Loop.init(testing.allocator);
|
||||||
defer loop.deinit(testing.allocator);
|
defer loop.deinit(testing.allocator);
|
||||||
var h = try init(testing.allocator, loop, (struct {
|
var h = try init(testing.allocator, loop, (struct {
|
||||||
fn callback(v: Async) void {
|
fn callback(v: *Async) void {
|
||||||
v.close(null);
|
v.close(null);
|
||||||
}
|
}
|
||||||
}).callback);
|
}).callback);
|
||||||
|
@ -20,7 +20,7 @@ test "Async: cancel timer" {
|
|||||||
}).callback, 5000, 5000);
|
}).callback, 5000, 5000);
|
||||||
|
|
||||||
var async_handle = try libuv.Async.init(testing.allocator, loop, (struct {
|
var async_handle = try libuv.Async.init(testing.allocator, loop, (struct {
|
||||||
fn callback(v: libuv.Async) void {
|
fn callback(v: *libuv.Async) void {
|
||||||
v.loop().stop();
|
v.loop().stop();
|
||||||
v.close(null);
|
v.close(null);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user