forked from vv/efemra
1
0
Fork 0

bump gen on remove and add

This commit is contained in:
Vivianne 2022-07-26 22:48:24 -07:00
parent b2a92c5c51
commit 32942c01c8
1 changed files with 8 additions and 6 deletions

View File

@ -94,7 +94,8 @@ pub fn Table(comptime K: type, comptime V: type) type {
} }
if (self.free_list.popOrNull()) |index| { if (self.free_list.popOrNull()) |index| {
const gen = self.gens.items[index]; // gen is bumped on remove *and* re-add. This way, 'active' slots are even and 'inactive' slots are odd.
self.gens.items[index] = self.gens.items[index] +% 1;
self.keys.items[index] = key; self.keys.items[index] = key;
self.values.items[index] = val; self.values.items[index] = val;
try self.lookup.putNoClobber(key, index); try self.lookup.putNoClobber(key, index);
@ -102,7 +103,7 @@ pub fn Table(comptime K: type, comptime V: type) type {
return AddResult{ return AddResult{
.id = .{ .id = .{
.index = index, .index = index,
.gen = gen, .gen = self.gens.items[index],
}, },
.added = true, .added = true,
}; };
@ -226,9 +227,10 @@ test "table across generation" {
// remove first item, then add a new one, then try to access first item! // remove first item, then add a new one, then try to access first item!
_ = try table.remove(table.find(48) orelse unreachable); _ = try table.remove(table.find(48) orelse unreachable);
try std.testing.expectEqual(@as(u8, 1), table.gens.items[0]);
const second_result = try table.add(99, .{ .a = 2, .b = 3 }); const second_result = try table.add(99, .{ .a = 2, .b = 3 });
try std.testing.expectEqual(@as(u8, 1), second_result.id.gen); try std.testing.expectEqual(@as(u8, 2), second_result.id.gen);
try std.testing.expect(!table.exists(first_result.id)); try std.testing.expect(!table.exists(first_result.id));
try std.testing.expectEqual(@as(?*TestVal, null), table.get(first_result.id)); try std.testing.expectEqual(@as(?*TestVal, null), table.get(first_result.id));
@ -248,12 +250,12 @@ pub fn RefTable(comptime K: type, comptime V: type) type {
/// Underlying table. /// Underlying table.
table: InternalTable, table: InternalTable,
/// Reference counts of the values. /// Reference counts of the values.
ref_counts: std.ArrayList(usize), ref_counts: std.ArrayList(u16),
pub fn init(allocator: std.mem.Allocator) Self { pub fn init(allocator: std.mem.Allocator) Self {
return Self{ return Self{
.table = Table(K, V).init(allocator), .table = Table(K, V).init(allocator),
.ref_counts = std.ArrayList(usize).init(allocator), .ref_counts = std.ArrayList(u16).init(allocator),
}; };
} }
@ -411,7 +413,7 @@ test "ref counting" {
first_result = try table.add(12, .{ .a = 6, .b = 5 }); first_result = try table.add(12, .{ .a = 6, .b = 5 });
try std.testing.expect(first_result.added); try std.testing.expect(first_result.added);
try std.testing.expectEqual(@as(u24, 0), first_result.id.index); try std.testing.expectEqual(@as(u24, 0), first_result.id.index);
try std.testing.expectEqual(@as(u8, 1), first_result.id.gen); try std.testing.expectEqual(@as(u8, 2), first_result.id.gen);
const second_result = try table.add(12, .{ .a = 1, .b = 2 }); const second_result = try table.add(12, .{ .a = 1, .b = 2 });
try std.testing.expect(!second_result.added); try std.testing.expect(!second_result.added);