authorgravatar for lucascarvalhosantos91@gmail.comLucas Santos <lucascarvalhosantos91@gmail.com> 2023-09-30 14:43:08-03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-30 16:17:22-07:00
log303181901b0a5e62ece5d4b786ee537a50d07709
treefc2ce51e937ee3499bb18e64271a3928f3db1655
parent937e8cb7051a3de537e11c2d52946f772f7449c3

Improve (Unmanaged)ArrayList.insert

(Unmanaged)ArrayList.insert has the same inefficiency as the old insertSlice. With the new addManyAt, the solution is trivial. Also improves the test "growing memory preserves contents". In the previous implementation, if any changes were made to the ArrayList memory growth policy (function growMemory), the list could end up with enough capacity to not trigger a memory growth, defeating the purpose of the test. The new implementation more robustly triggers a memory growth.

1 files changed, 10 insertions(+), 10 deletions(-)

lib/std/array_list.zig+10-10
...@@ -146,8 +146,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -146,8 +146,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
146 /// This operation is O(N).146 /// This operation is O(N).
147 /// Invalidates pointers if additional memory is needed.147 /// Invalidates pointers if additional memory is needed.
148 pub fn insert(self: *Self, n: usize, item: T) Allocator.Error!void {148 pub fn insert(self: *Self, n: usize, item: T) Allocator.Error!void {
149 try self.ensureUnusedCapacity(1);149 const dst = try self.addManyAt(n, 1);
150 self.insertAssumeCapacity(n, item);150 dst[0] = item;
151 }151 }
152152
153 /// Insert `item` at index `n`. Moves `list[n .. list.len]` to higher indices to make room.153 /// Insert `item` at index `n`. Moves `list[n .. list.len]` to higher indices to make room.
...@@ -702,8 +702,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -702,8 +702,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
702 /// This operation is O(N).702 /// This operation is O(N).
703 /// Invalidates pointers if additional memory is needed.703 /// Invalidates pointers if additional memory is needed.
704 pub fn insert(self: *Self, allocator: Allocator, n: usize, item: T) Allocator.Error!void {704 pub fn insert(self: *Self, allocator: Allocator, n: usize, item: T) Allocator.Error!void {
705 try self.ensureUnusedCapacity(allocator, 1);705 const dst = try self.addManyAt(allocator, n, 1);
706 self.insertAssumeCapacity(n, item);706 dst[0] = item;
707 }707 }
708708
709 /// Insert `item` at index `n`. Moves `list[n .. list.len]` to higher indices to make room.709 /// Insert `item` at index `n`. Moves `list[n .. list.len]` to higher indices to make room.
...@@ -1761,33 +1761,33 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {...@@ -1761,33 +1761,33 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
1761}1761}
17621762
1763test "std.ArrayList/ArrayListUnmanaged growing memory preserves contents" {1763test "std.ArrayList/ArrayListUnmanaged growing memory preserves contents" {
1764 // Shrink the list after every insertion to ensure that a memory growth
1765 // will be triggered in the next operation.
1764 const a = std.testing.allocator;1766 const a = std.testing.allocator;
1765 {1767 {
1766 var list = ArrayList(u8).init(a);1768 var list = ArrayList(u8).init(a);
1767 defer list.deinit();1769 defer list.deinit();
1768 try list.ensureTotalCapacityPrecise(1);
17691770
1770 (try list.addManyAsArray(4)).* = "abcd".*;1771 (try list.addManyAsArray(4)).* = "abcd".*;
1771 try list.ensureTotalCapacityPrecise(4);1772 list.shrinkAndFree(4);
17721773
1773 try list.appendSlice("efgh");1774 try list.appendSlice("efgh");
1774 try testing.expectEqualSlices(u8, list.items, "abcdefgh");1775 try testing.expectEqualSlices(u8, list.items, "abcdefgh");
1775 try list.ensureTotalCapacityPrecise(8);1776 list.shrinkAndFree(8);
17761777
1777 try list.insertSlice(4, "ijkl");1778 try list.insertSlice(4, "ijkl");
1778 try testing.expectEqualSlices(u8, list.items, "abcdijklefgh");1779 try testing.expectEqualSlices(u8, list.items, "abcdijklefgh");
1779 }1780 }
1780 {1781 {
1781 var list = ArrayListUnmanaged(u8){};1782 var list = ArrayListUnmanaged(u8){};
1782 try list.ensureTotalCapacityPrecise(a, 1);
1783 defer list.deinit(a);1783 defer list.deinit(a);
17841784
1785 (try list.addManyAsArray(a, 4)).* = "abcd".*;1785 (try list.addManyAsArray(a, 4)).* = "abcd".*;
1786 try list.ensureTotalCapacityPrecise(a, 4);1786 list.shrinkAndFree(a, 4);
17871787
1788 try list.appendSlice(a, "efgh");1788 try list.appendSlice(a, "efgh");
1789 try testing.expectEqualSlices(u8, list.items, "abcdefgh");1789 try testing.expectEqualSlices(u8, list.items, "abcdefgh");
1790 try list.ensureTotalCapacityPrecise(a, 8);1790 list.shrinkAndFree(a, 8);
17911791
1792 try list.insertSlice(a, 4, "ijkl");1792 try list.insertSlice(a, 4, "ijkl");
1793 try testing.expectEqualSlices(u8, list.items, "abcdijklefgh");1793 try testing.expectEqualSlices(u8, list.items, "abcdijklefgh");