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;
}
/// 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
/// does not do any memory size accounting with max_size/page_size.
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(
page.memory,
self.cursor.style,
) catch |err| switch (err) {
// Our style map is full. Let's allocate a new page by doubling
// the size and then try again.
error.OutOfMemory => md: {
const node = try self.pages.adjustCapacity(
self.cursor.page_pin.page,
.{ .styles = page.capacity.styles * 2 },
);
) catch |err| md: {
switch (err) {
// Our style map is full. Let's allocate a new page by doubling
// the size and then try again.
error.OutOfMemory => {
const node = try self.pages.adjustCapacity(
self.cursor.page_pin.page,
.{ .styles = page.capacity.styles * 2 },
);
// Since this modifies our cursor page, we need to reload
self.cursorReload();
page = &node.data;
},
page = &node.data;
break :md try page.styles.upsert(
page.memory,
self.cursor.style,
);
},
// We've run out of style IDs. This is fixed by doing a page
// compaction.
error.Overflow => {
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_ref = &md.ref;