mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
terminal: RefCountedSet has Context variant methods
This commit is contained in:
@ -205,12 +205,15 @@ pub fn RefCountedSet(
|
|||||||
///
|
///
|
||||||
/// If the set has no more room, then an OutOfMemory error is returned.
|
/// If the set has no more room, then an OutOfMemory error is returned.
|
||||||
pub fn add(self: *Self, base: anytype, value: T) AddError!Id {
|
pub fn add(self: *Self, base: anytype, value: T) AddError!Id {
|
||||||
|
return try self.addContext(base, value, self.context);
|
||||||
|
}
|
||||||
|
pub fn addContext(self: *Self, base: anytype, value: T, ctx: Context) AddError!Id {
|
||||||
const items = self.items.ptr(base);
|
const items = self.items.ptr(base);
|
||||||
|
|
||||||
// Trim dead items from the end of the list.
|
// Trim dead items from the end of the list.
|
||||||
while (self.next_id > 1 and items[self.next_id - 1].meta.ref == 0) {
|
while (self.next_id > 1 and items[self.next_id - 1].meta.ref == 0) {
|
||||||
self.next_id -= 1;
|
self.next_id -= 1;
|
||||||
self.deleteItem(base, self.next_id);
|
self.deleteItem(base, self.next_id, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we still don't have an available ID, we can't continue.
|
// If we still don't have an available ID, we can't continue.
|
||||||
@ -232,7 +235,7 @@ pub fn RefCountedSet(
|
|||||||
return AddError.OutOfMemory;
|
return AddError.OutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = self.upsert(base, value, self.next_id);
|
const id = self.upsert(base, value, self.next_id, ctx);
|
||||||
items[id].meta.ref += 1;
|
items[id].meta.ref += 1;
|
||||||
|
|
||||||
if (id == self.next_id) self.next_id += 1;
|
if (id == self.next_id) self.next_id += 1;
|
||||||
@ -251,27 +254,30 @@ pub fn RefCountedSet(
|
|||||||
///
|
///
|
||||||
/// If the set has no more room, then an OutOfMemory error is returned.
|
/// If the set has no more room, then an OutOfMemory error is returned.
|
||||||
pub fn addWithId(self: *Self, base: anytype, value: T, id: Id) AddError!?Id {
|
pub fn addWithId(self: *Self, base: anytype, value: T, id: Id) AddError!?Id {
|
||||||
|
return try self.addWithIdContext(base, value, id, self.context);
|
||||||
|
}
|
||||||
|
pub fn addWithIdContext(self: *Self, base: anytype, value: T, id: Id, ctx: Context) AddError!?Id {
|
||||||
const items = self.items.ptr(base);
|
const items = self.items.ptr(base);
|
||||||
|
|
||||||
if (id < self.next_id) {
|
if (id < self.next_id) {
|
||||||
if (items[id].meta.ref == 0) {
|
if (items[id].meta.ref == 0) {
|
||||||
self.deleteItem(base, id);
|
self.deleteItem(base, id, ctx);
|
||||||
|
|
||||||
const added_id = self.upsert(base, value, id);
|
const added_id = self.upsert(base, value, id, ctx);
|
||||||
|
|
||||||
items[added_id].meta.ref += 1;
|
items[added_id].meta.ref += 1;
|
||||||
|
|
||||||
self.living += 1;
|
self.living += 1;
|
||||||
|
|
||||||
return if (added_id == id) null else added_id;
|
return if (added_id == id) null else added_id;
|
||||||
} else if (self.context.eql(base, value, items[id].value)) {
|
} else if (ctx.eql(base, value, items[id].value)) {
|
||||||
items[id].meta.ref += 1;
|
items[id].meta.ref += 1;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return try self.add(base, value);
|
return try self.addContext(base, value, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increment an item's reference count by 1.
|
/// Increment an item's reference count by 1.
|
||||||
@ -377,7 +383,7 @@ pub fn RefCountedSet(
|
|||||||
|
|
||||||
/// Delete an item, removing any references from
|
/// Delete an item, removing any references from
|
||||||
/// the table, and freeing its ID to be re-used.
|
/// the table, and freeing its ID to be re-used.
|
||||||
fn deleteItem(self: *Self, base: anytype, id: Id) void {
|
fn deleteItem(self: *Self, base: anytype, id: Id, ctx: Context) void {
|
||||||
const table = self.table.ptr(base);
|
const table = self.table.ptr(base);
|
||||||
const items = self.items.ptr(base);
|
const items = self.items.ptr(base);
|
||||||
|
|
||||||
@ -390,7 +396,7 @@ pub fn RefCountedSet(
|
|||||||
if (comptime @hasDecl(Context, "deleted")) {
|
if (comptime @hasDecl(Context, "deleted")) {
|
||||||
// Inform the context struct that we're
|
// Inform the context struct that we're
|
||||||
// deleting the dead item's value for good.
|
// deleting the dead item's value for good.
|
||||||
self.context.deleted(base, item.value);
|
ctx.deleted(base, item.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.psl_stats[item.meta.psl] -= 1;
|
self.psl_stats[item.meta.psl] -= 1;
|
||||||
@ -419,11 +425,11 @@ pub fn RefCountedSet(
|
|||||||
|
|
||||||
/// Find an item in the table and return its ID.
|
/// Find an item in the table and return its ID.
|
||||||
/// If the item does not exist in the table, null is returned.
|
/// If the item does not exist in the table, null is returned.
|
||||||
fn lookup(self: *Self, base: anytype, value: T) ?Id {
|
fn lookup(self: *Self, base: anytype, value: T, ctx: Context) ?Id {
|
||||||
const table = self.table.ptr(base);
|
const table = self.table.ptr(base);
|
||||||
const items = self.items.ptr(base);
|
const items = self.items.ptr(base);
|
||||||
|
|
||||||
const hash: u64 = self.context.hash(base, value);
|
const hash: u64 = ctx.hash(base, value);
|
||||||
|
|
||||||
for (0..self.max_psl + 1) |i| {
|
for (0..self.max_psl + 1) |i| {
|
||||||
const p: usize = @intCast((hash + i) & self.layout.table_mask);
|
const p: usize = @intCast((hash + i) & self.layout.table_mask);
|
||||||
@ -455,7 +461,7 @@ pub fn RefCountedSet(
|
|||||||
// If the item is a part of the same probe sequence,
|
// If the item is a part of the same probe sequence,
|
||||||
// we check if it matches the value we're looking for.
|
// we check if it matches the value we're looking for.
|
||||||
if (item.meta.psl == i and
|
if (item.meta.psl == i and
|
||||||
self.context.eql(base, value, item.value))
|
ctx.eql(base, value, item.value))
|
||||||
{
|
{
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -468,9 +474,9 @@ pub fn RefCountedSet(
|
|||||||
/// for it if not present. If a new item is added, `new_id` will
|
/// for it if not present. If a new item is added, `new_id` will
|
||||||
/// be used as the ID. If an existing item is found, the `new_id`
|
/// be used as the ID. If an existing item is found, the `new_id`
|
||||||
/// is ignored and the existing item's ID is returned.
|
/// is ignored and the existing item's ID is returned.
|
||||||
fn upsert(self: *Self, base: anytype, value: T, new_id: Id) Id {
|
fn upsert(self: *Self, base: anytype, value: T, new_id: Id, ctx: Context) Id {
|
||||||
// If the item already exists, return it.
|
// If the item already exists, return it.
|
||||||
if (self.lookup(base, value)) |id| return id;
|
if (self.lookup(base, value, ctx)) |id| return id;
|
||||||
|
|
||||||
const table = self.table.ptr(base);
|
const table = self.table.ptr(base);
|
||||||
const items = self.items.ptr(base);
|
const items = self.items.ptr(base);
|
||||||
@ -481,7 +487,7 @@ pub fn RefCountedSet(
|
|||||||
.meta = .{ .psl = 0, .ref = 0 },
|
.meta = .{ .psl = 0, .ref = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const hash: u64 = self.context.hash(base, value);
|
const hash: u64 = ctx.hash(base, value);
|
||||||
|
|
||||||
var held_id: Id = new_id;
|
var held_id: Id = new_id;
|
||||||
var held_item: *Item = &new_item;
|
var held_item: *Item = &new_item;
|
||||||
@ -510,7 +516,7 @@ pub fn RefCountedSet(
|
|||||||
if (comptime @hasDecl(Context, "deleted")) {
|
if (comptime @hasDecl(Context, "deleted")) {
|
||||||
// Inform the context struct that we're
|
// Inform the context struct that we're
|
||||||
// deleting the dead item's value for good.
|
// deleting the dead item's value for good.
|
||||||
self.context.deleted(base, item.value);
|
ctx.deleted(base, item.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
chosen_id = id;
|
chosen_id = id;
|
||||||
|
Reference in New Issue
Block a user