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: {
switch (err) {
// Our style map is full. Let's allocate a new page by doubling // Our style map is full. Let's allocate a new page by doubling
// the size and then try again. // the size and then try again.
error.OutOfMemory => md: { error.OutOfMemory => {
const node = try self.pages.adjustCapacity( const node = try self.pages.adjustCapacity(
self.cursor.page_pin.page, self.cursor.page_pin.page,
.{ .styles = page.capacity.styles * 2 }, .{ .styles = page.capacity.styles * 2 },
); );
page = &node.data;
},
// 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;
},
}
// Since this modifies our cursor page, we need to reload // Since this modifies our cursor page, we need to reload
self.cursorReload(); self.cursorReload();
page = &node.data;
break :md try page.styles.upsert( break :md try page.styles.upsert(
page.memory, page.memory,
self.cursor.style, self.cursor.style,
); );
},
error.Overflow => return err, // TODO
}; };
self.cursor.style_id = md.id; self.cursor.style_id = md.id;
self.cursor.style_ref = &md.ref; self.cursor.style_ref = &md.ref;