core: deref the font group when not used

This commit is contained in:
Mitchell Hashimoto
2024-04-01 15:43:43 -07:00
parent 6d7053a1ad
commit 5de88fe3f8
2 changed files with 33 additions and 5 deletions

View File

@ -54,6 +54,7 @@ rt_app: *apprt.runtime.App,
rt_surface: *apprt.runtime.Surface, rt_surface: *apprt.runtime.Surface,
/// The font structures /// The font structures
font_group_key: font.GroupCacheSet.Key,
font_size: font.face.DesiredSize, font_size: font.face.DesiredSize,
/// The renderer for this surface. /// The renderer for this surface.
@ -320,7 +321,10 @@ pub fn init(
// Setup our font group. This will reuse an existing font group if // Setup our font group. This will reuse an existing font group if
// it was already loaded. // it was already loaded.
const font_group = try app.font_group_set.groupInit(config, font_size); const font_group_key, const font_group = try app.font_group_set.groupRef(
config,
font_size,
);
// Pre-calculate our initial cell size ourselves. // Pre-calculate our initial cell size ourselves.
const cell_size = try renderer.CellSize.init(alloc, font_group); const cell_size = try renderer.CellSize.init(alloc, font_group);
@ -406,6 +410,7 @@ pub fn init(
.app = app, .app = app,
.rt_app = rt_app, .rt_app = rt_app,
.rt_surface = rt_surface, .rt_surface = rt_surface,
.font_group_key = font_group_key,
.font_size = font_size, .font_size = font_size,
.renderer = renderer_impl, .renderer = renderer_impl,
.renderer_thread = render_thread, .renderer_thread = render_thread,
@ -525,6 +530,9 @@ pub fn deinit(self: *Surface) void {
self.alloc.destroy(v); self.alloc.destroy(v);
} }
// Clean up our font group
self.app.font_group_set.groupDeref(self.font_group_key);
// Clean up our render state // Clean up our render state
if (self.renderer_state.preedit) |p| self.alloc.free(p.codepoints); if (self.renderer_state.preedit) |p| self.alloc.free(p.codepoints);
self.alloc.destroy(self.renderer_state.mutex); self.alloc.destroy(self.renderer_state.mutex);

View File

@ -61,6 +61,7 @@ pub fn init(alloc: Allocator) !GroupCacheSet {
pub fn deinit(self: *GroupCacheSet) void { pub fn deinit(self: *GroupCacheSet) void {
var it = self.map.iterator(); var it = self.map.iterator();
while (it.next()) |entry| { while (it.next()) |entry| {
entry.key_ptr.deinit();
const ref = entry.value_ptr.*; const ref = entry.value_ptr.*;
ref.cache.deinit(self.alloc); ref.cache.deinit(self.alloc);
self.alloc.destroy(ref.cache); self.alloc.destroy(ref.cache);
@ -79,11 +80,11 @@ pub fn deinit(self: *GroupCacheSet) void {
/// 1. If it is present, the ref count will be incremented. /// 1. If it is present, the ref count will be incremented.
/// ///
/// This is NOT thread-safe. /// This is NOT thread-safe.
pub fn groupInit( pub fn groupRef(
self: *GroupCacheSet, self: *GroupCacheSet,
config: *const Config, config: *const Config,
font_size: DesiredSize, font_size: DesiredSize,
) !*GroupCache { ) !struct { Key, *GroupCache } {
var key = try Key.init(self.alloc, config); var key = try Key.init(self.alloc, config);
errdefer key.deinit(); errdefer key.deinit();
@ -94,7 +95,7 @@ pub fn groupInit(
// Increment our ref count and return the cache // Increment our ref count and return the cache
gop.value_ptr.ref += 1; gop.value_ptr.ref += 1;
return gop.value_ptr.cache; return .{ gop.key_ptr.*, gop.value_ptr.cache };
} }
errdefer self.map.removeByPtr(gop.key_ptr); errdefer self.map.removeByPtr(gop.key_ptr);
@ -210,7 +211,26 @@ pub fn groupInit(
}); });
errdefer cache.deinit(self.alloc); errdefer cache.deinit(self.alloc);
return gop.value_ptr.cache; return .{ gop.key_ptr.*, gop.value_ptr.cache };
}
/// Decrement the ref count for the given key. If the ref count is zero,
/// the GroupCache will be deinitialized and removed from the map.j:w
pub fn groupDeref(self: *GroupCacheSet, key: Key) void {
const entry = self.map.getEntry(key) orelse return;
assert(entry.value_ptr.ref >= 1);
// If we have more than one reference, decrement and return.
if (entry.value_ptr.ref > 1) {
entry.value_ptr.ref -= 1;
return;
}
// We are at a zero ref count so deinit the group and remove.
entry.key_ptr.deinit();
entry.value_ptr.cache.deinit(self.alloc);
self.alloc.destroy(entry.value_ptr.cache);
self.map.removeByPtr(entry.key_ptr);
} }
/// Map of font configurations to GroupCache instances. The GroupCache /// Map of font configurations to GroupCache instances. The GroupCache