Commit 89bd29a905

Erik Arvstedt <erik.arvstedt@gmail.com>
2023-06-12 22:21:31
arena_allocator/reset: avoid zero-capacity allocations
1. When the arena is already empty, resetting with `retain_capacity` no longer results in allocating a buffer with zero capacity. This behavior was previously intended by the `(current_capacity == 0)` check, but wasn't correctly implemented. 2. Resetting with `.{ .retain_with_limit = 0 }` is now equivalent to `free_all` and a new buffer with zero capacity is no longer created. This is a useful side-effect of the above fixes.
1 parent 5d3c8f4
Changed files (1)
lib
lib/std/heap/arena_allocator.zig
@@ -108,21 +108,18 @@ pub const ArenaAllocator = struct {
         // Thus, only the first hand full of calls to reset() will actually need to iterate the linked
         // list, all future calls are just taking the first node, and only resetting the `end_index`
         // value.
-        const current_capacity = if (mode != .free_all)
-            @sizeOf(BufNode) + self.queryCapacity() // we need at least space for exactly one node + the current capacity
-        else
-            0;
-        if (mode == .free_all or current_capacity == 0) {
+        const requested_capacity = switch (mode) {
+            .retain_capacity => self.queryCapacity(),
+            .retain_with_limit => |limit| std.math.min(limit, self.queryCapacity()),
+            .free_all => 0,
+        };
+        if (requested_capacity == 0) {
             // just reset when we don't have anything to reallocate
             self.deinit();
             self.state = State{};
             return true;
         }
-        const total_size = switch (mode) {
-            .retain_capacity => current_capacity,
-            .retain_with_limit => |limit| std.math.min(@sizeOf(BufNode) + limit, current_capacity),
-            .free_all => unreachable,
-        };
+        const total_size = requested_capacity + @sizeOf(BufNode);
         const align_bits = std.math.log2_int(usize, @alignOf(BufNode));
         // Free all nodes except for the last one
         var it = self.state.buffer_list.first;