terminal: handle style ID overflow

This commit is contained in:
Mitchell Hashimoto
2024-03-11 19:23:27 -07:00
parent 5e68bc60e0
commit dc04cc1317
2 changed files with 39 additions and 17 deletions

View File

@ -1573,6 +1573,18 @@ pub fn adjustCapacity(
return new_page; return new_page;
} }
/// Compact a page, reallocating to minimize the amount of memory
/// required for the page. This is useful when we've overflowed ID
/// spaces, are archiving a page, etc.
///
/// Note today: this doesn't minimize the memory usage, but it does
/// fix style ID overflow. A future update can shrink the memory
/// allocation.
pub fn compact(self: *PageList, page: *List.Node) !*List.Node {
// Adjusting capacity with no adjustments forces a reallocation.
return try self.adjustCapacity(page, .{});
}
/// Create a new page node. This does not add it to the list and this /// Create a new page node. This does not add it to the list and this
/// does not do any memory size accounting with max_size/page_size. /// does not do any memory size accounting with max_size/page_size.
fn createPage(self: *PageList, cap: Capacity) !*List.Node { fn createPage(self: *PageList, cap: Capacity) !*List.Node {

View File

@ -971,26 +971,36 @@ pub fn manualStyleUpdate(self: *Screen) !void {
const md = page.styles.upsert( const md = page.styles.upsert(
page.memory, page.memory,
self.cursor.style, self.cursor.style,
) catch |err| switch (err) { ) catch |err| md: {
// Our style map is full. Let's allocate a new page by doubling switch (err) {
// the size and then try again. // Our style map is full. Let's allocate a new page by doubling
error.OutOfMemory => md: { // the size and then try again.
const node = try self.pages.adjustCapacity( error.OutOfMemory => {
self.cursor.page_pin.page, const node = try self.pages.adjustCapacity(
.{ .styles = page.capacity.styles * 2 }, self.cursor.page_pin.page,
); .{ .styles = page.capacity.styles * 2 },
);
// Since this modifies our cursor page, we need to reload page = &node.data;
self.cursorReload(); },
page = &node.data; // We've run out of style IDs. This is fixed by doing a page
break :md try page.styles.upsert( // compaction.
page.memory, error.Overflow => {
self.cursor.style, const node = try self.pages.compact(
); self.cursor.page_pin.page,
}, );
page = &node.data;
},
}
error.Overflow => return err, // TODO // Since this modifies our cursor page, we need to reload
self.cursorReload();
break :md try page.styles.upsert(
page.memory,
self.cursor.style,
);
}; };
self.cursor.style_id = md.id; self.cursor.style_id = md.id;
self.cursor.style_ref = &md.ref; self.cursor.style_ref = &md.ref;