authorgravatar for sentientwaffle@gmail.comsentientwaffle <sentientwaffle@gmail.com> 2023-06-09 12:52:36-07:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-06-10 02:24:35+03:00
logf04e65bc09ab77eafc317b2d2981970509aae6af
tree707964d29fbc65bc693fe543a47c14f5231f4e52
parent99fe2a23c0b45395be3c71192aeaeaea77e1fb0c

std.hash_map: fetchRemove increment available

To avoid leaking slots, `fetchRemove` must increment `available` (when the "fetch" succeeds). Without the `available += 1`, the added test `"std.hash_map repeat fetchRemove"` fails with run test std-x86-linux-none-Debug: error: thread 432734 panic: integer overflow .../zig/lib/std/hash_map.zig:1365:28: 0x6471d5 in getOrPutAssumeCapacityAdapted__anon_47495 (test) self.available -= 1; ^ .../zig/lib/std/hash_map.zig:1308:62: 0x616950 in getOrPutAssumeCapacityContext (test) const result = self.getOrPutAssumeCapacityAdapted(key, ctx); ^ Alternatively, `fetchRemove` could call `removeByIndex`, though that would entail calling `header()` twice instead of once.

1 files changed, 25 insertions(+), 0 deletions(-)

lib/std/hash_map.zig+25
......@@ -1113,6 +1113,7 @@ pub fn HashMapUnmanaged(
11131113 old_key.* = undefined;
11141114 old_val.* = undefined;
11151115 self.size -= 1;
1116 self.available += 1;
11161117 return result;
11171118 }
11181119
......@@ -2193,3 +2194,27 @@ test "std.hash_map removeByPtr 0 sized key" {
21932194
21942195 try testing.expect(map.count() == 0);
21952196}
2197
2198test "std.hash_map repeat fetchRemove" {
2199 var map = AutoHashMapUnmanaged(u64, void){};
2200 defer map.deinit(testing.allocator);
2201
2202 try map.ensureTotalCapacity(testing.allocator, 4);
2203
2204 map.putAssumeCapacity(0, {});
2205 map.putAssumeCapacity(1, {});
2206 map.putAssumeCapacity(2, {});
2207 map.putAssumeCapacity(3, {});
2208
2209 // fetchRemove() should make slots available.
2210 var i: usize = 0;
2211 while (i < 10) : (i += 1) {
2212 try testing.expect(map.fetchRemove(3) != null);
2213 map.putAssumeCapacity(3, {});
2214 }
2215
2216 try testing.expect(map.get(0) != null);
2217 try testing.expect(map.get(1) != null);
2218 try testing.expect(map.get(2) != null);
2219 try testing.expect(map.get(3) != null);
2220}