mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-19 14:00:29 +00:00
deps: update zig-objc
This update also fixes a memory leak that was caused by blocks not being deallocated and just collecting every single frame, slowly accumulating memory until OOM.
This commit is contained in:
@@ -28,7 +28,7 @@ pub const Options = struct {
|
||||
/// MTLCommandBuffer
|
||||
buffer: objc.Object,
|
||||
|
||||
block: CompletionBlock,
|
||||
block: CompletionBlock.Context,
|
||||
|
||||
/// Begin encoding a frame.
|
||||
pub fn begin(
|
||||
@@ -47,7 +47,7 @@ pub fn begin(
|
||||
|
||||
// Create our block to register for completion updates.
|
||||
// The block is deallocated by the objC runtime on success.
|
||||
const block = try CompletionBlock.init(
|
||||
const block = CompletionBlock.init(
|
||||
.{
|
||||
.renderer = renderer,
|
||||
.target = target,
|
||||
@@ -55,7 +55,6 @@ pub fn begin(
|
||||
},
|
||||
&bufferCompleted,
|
||||
);
|
||||
errdefer block.deinit();
|
||||
|
||||
return .{ .buffer = buffer, .block = block };
|
||||
}
|
||||
@@ -114,24 +113,23 @@ pub inline fn complete(self: *Self, sync: bool) void {
|
||||
// If we don't need to complete synchronously,
|
||||
// we add our block as a completion handler.
|
||||
//
|
||||
// It will be deallocated by the objc runtime on success.
|
||||
// It will be copied when we add the handler, and then the
|
||||
// copy will be deallocated by the objc runtime on success.
|
||||
if (!sync) {
|
||||
self.buffer.msgSend(
|
||||
void,
|
||||
objc.sel("addCompletedHandler:"),
|
||||
.{self.block.context},
|
||||
.{&self.block},
|
||||
);
|
||||
}
|
||||
|
||||
self.buffer.msgSend(void, objc.sel("commit"), .{});
|
||||
|
||||
// If we need to complete synchronously, we wait until
|
||||
// the buffer is completed and call the callback directly,
|
||||
// deiniting the block after we're done.
|
||||
// the buffer is completed and invoke the block directly.
|
||||
if (sync) {
|
||||
self.buffer.msgSend(void, "waitUntilCompleted", .{});
|
||||
self.block.context.sync = true;
|
||||
bufferCompleted(self.block.context, self.buffer.value);
|
||||
self.block.deinit();
|
||||
self.block.sync = true;
|
||||
CompletionBlock.invoke(&self.block, .{self.buffer.value});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,13 +54,11 @@ pub inline fn setSurface(self: *IOSurfaceLayer, surface: *IOSurface) !void {
|
||||
//
|
||||
// We release in the callback after setting the contents.
|
||||
surface.retain();
|
||||
// We also need to retain the layer itself to make sure it
|
||||
// isn't destroyed before the callback completes, since if
|
||||
// that happens it will try to interact with a deallocated
|
||||
// object.
|
||||
_ = self.layer.retain();
|
||||
// NOTE: Since `self.layer` is passed as an `objc.c.id`, it's
|
||||
// automatically retained when the block is copied, so we
|
||||
// don't need to retain it ourselves like with the surface.
|
||||
|
||||
var block = try SetSurfaceBlock.init(.{
|
||||
var block = SetSurfaceBlock.init(.{
|
||||
.layer = self.layer.value,
|
||||
.surface = surface,
|
||||
}, &setSurfaceCallback);
|
||||
@@ -68,15 +66,15 @@ pub inline fn setSurface(self: *IOSurfaceLayer, surface: *IOSurface) !void {
|
||||
// We check if we're on the main thread and run the block directly if so.
|
||||
const NSThread = objc.getClass("NSThread").?;
|
||||
if (NSThread.msgSend(bool, "isMainThread", .{})) {
|
||||
setSurfaceCallback(block.context);
|
||||
block.deinit();
|
||||
setSurfaceCallback(&block);
|
||||
} else {
|
||||
// NOTE: The block will automatically be deallocated by the objc
|
||||
// runtime once it's executed, so there's no need to deinit it.
|
||||
// NOTE: The block will be copied when we pass it to dispatch_async,
|
||||
// and then automatically be deallocated by the objc runtime
|
||||
// once it's executed.
|
||||
|
||||
macos.dispatch.dispatch_async(
|
||||
@ptrCast(macos.dispatch.queue.getMain()),
|
||||
@ptrCast(block.context),
|
||||
@ptrCast(&block),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -100,10 +98,7 @@ fn setSurfaceCallback(
|
||||
const surface: *IOSurface = block.surface;
|
||||
|
||||
// See explanation of why we retain and release in `setSurface`.
|
||||
defer {
|
||||
surface.release();
|
||||
layer.release();
|
||||
}
|
||||
defer surface.release();
|
||||
|
||||
// We check to see if the surface is the appropriate size for
|
||||
// the layer, if it's not then we discard it. This is because
|
||||
|
||||
Reference in New Issue
Block a user