| ... | @@ -34,6 +34,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -34,6 +34,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 34 | capacity: usize, | 34 | capacity: usize, |
| 35 | allocator: Allocator, | 35 | allocator: Allocator, |
| 36 | | 36 | |
| | 37 | /// Used to detect memory safety violations. |
| | 38 | pointer_stability: debug.SafetyLock = .{}, |
| | 39 | |
| 37 | pub const Slice = if (alignment) |a| ([]align(a.toByteUnits()) T) else []T; | 40 | pub const Slice = if (alignment) |a| ([]align(a.toByteUnits()) T) else []T; |
| 38 | | 41 | |
| 39 | pub fn SentinelSlice(comptime s: T) type { | 42 | pub fn SentinelSlice(comptime s: T) type { |
| ... | @@ -60,11 +63,29 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -60,11 +63,29 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 60 | | 63 | |
| 61 | /// Release all allocated memory. | 64 | /// Release all allocated memory. |
| 62 | pub fn deinit(self: Self) void { | 65 | pub fn deinit(self: Self) void { |
| | 66 | self.pointer_stability.assertUnlocked(); |
| 63 | if (@sizeOf(T) > 0) { | 67 | if (@sizeOf(T) > 0) { |
| 64 | self.allocator.free(self.allocatedSlice()); | 68 | self.allocator.free(self.allocatedSlice()); |
| 65 | } | 69 | } |
| 66 | } | 70 | } |
| 67 | | 71 | |
| | 72 | /// Puts the array list into a state where any method call that would |
| | 73 | /// cause an existing value pointer to become invalidated will |
| | 74 | /// instead trigger an assertion. |
| | 75 | /// |
| | 76 | /// An additional call to `lockPointers` in such state also triggers an |
| | 77 | /// assertion. |
| | 78 | /// |
| | 79 | /// `unlockPointers` returns the array list to the previous state. |
| | 80 | pub fn lockPointers(self: *Self) void { |
| | 81 | self.pointer_stability.lock(); |
| | 82 | } |
| | 83 | |
| | 84 | /// Undoes a call to `lockPointers`. |
| | 85 | pub fn unlockPointers(self: *Self) void { |
| | 86 | self.pointer_stability.unlock(); |
| | 87 | } |
| | 88 | |
| 68 | /// ArrayList takes ownership of the passed in slice. The slice must have been | 89 | /// ArrayList takes ownership of the passed in slice. The slice must have been |
| 69 | /// allocated with `gpa`. | 90 | /// allocated with `gpa`. |
| 70 | /// Deinitialize with `deinit` or use `toOwnedSlice`. | 91 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| ... | @@ -90,6 +111,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -90,6 +111,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 90 | /// Initializes an ArrayList with the `items` and `capacity` fields | 111 | /// Initializes an ArrayList with the `items` and `capacity` fields |
| 91 | /// of this ArrayList. Empties this ArrayList. | 112 | /// of this ArrayList. Empties this ArrayList. |
| 92 | pub fn moveToUnmanaged(self: *Self) Aligned(T, alignment) { | 113 | pub fn moveToUnmanaged(self: *Self) Aligned(T, alignment) { |
| | 114 | self.pointer_stability.assertUnlocked(); |
| 93 | const allocator = self.allocator; | 115 | const allocator = self.allocator; |
| 94 | const result: Aligned(T, alignment) = .{ .items = self.items, .capacity = self.capacity }; | 116 | const result: Aligned(T, alignment) = .{ .items = self.items, .capacity = self.capacity }; |
| 95 | self.* = init(allocator); | 117 | self.* = init(allocator); |
| ... | @@ -146,6 +168,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -146,6 +168,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 146 | /// Asserts that there is enough capacity for the new item. | 168 | /// Asserts that there is enough capacity for the new item. |
| 147 | /// Asserts that the index is in bounds or equal to the length. | 169 | /// Asserts that the index is in bounds or equal to the length. |
| 148 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { | 170 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { |
| | 171 | self.pointer_stability.lock(); |
| | 172 | defer self.pointer_stability.unlock(); |
| | 173 | |
| 149 | assert(self.items.len < self.capacity); | 174 | assert(self.items.len < self.capacity); |
| 150 | self.items.len += 1; | 175 | self.items.len += 1; |
| 151 | | 176 | |
| ... | @@ -167,6 +192,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -167,6 +192,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 167 | if (self.capacity >= new_len) | 192 | if (self.capacity >= new_len) |
| 168 | return addManyAtAssumeCapacity(self, index, count); | 193 | return addManyAtAssumeCapacity(self, index, count); |
| 169 | | 194 | |
| | 195 | self.pointer_stability.lock(); |
| | 196 | defer self.pointer_stability.unlock(); |
| 170 | // Here we avoid copying allocated but unused bytes by | 197 | // Here we avoid copying allocated but unused bytes by |
| 171 | // attempting a resize in place, and falling back to allocating | 198 | // attempting a resize in place, and falling back to allocating |
| 172 | // a new buffer and doing our own copy. With a realloc() call, | 199 | // a new buffer and doing our own copy. With a realloc() call, |
| ... | @@ -199,8 +226,6 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -199,8 +226,6 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 199 | /// elements, which becomes invalid after various `ArrayList` | 226 | /// elements, which becomes invalid after various `ArrayList` |
| 200 | /// operations. | 227 | /// operations. |
| 201 | /// Asserts that there is enough capacity for the new elements. | 228 | /// Asserts that there is enough capacity for the new elements. |
| 202 | /// Invalidates pre-existing pointers to elements at and after `index`, but | | |
| 203 | /// does not invalidate any before that. | | |
| 204 | /// Asserts that the index is in bounds or equal to the length. | 229 | /// Asserts that the index is in bounds or equal to the length. |
| 205 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { | 230 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| 206 | const new_len = self.items.len + count; | 231 | const new_len = self.items.len + count; |
| ... | @@ -379,6 +404,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -379,6 +404,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 379 | /// Invalidates element pointers for the elements `items[new_len..]`. | 404 | /// Invalidates element pointers for the elements `items[new_len..]`. |
| 380 | /// Asserts that the new length is less than or equal to the previous length. | 405 | /// Asserts that the new length is less than or equal to the previous length. |
| 381 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | 406 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| | 407 | self.pointer_stability.lock(); |
| | 408 | defer self.pointer_stability.unlock(); |
| | 409 | |
| 382 | assert(new_len <= self.items.len); | 410 | assert(new_len <= self.items.len); |
| 383 | @memset(self.items[new_len..], undefined); | 411 | @memset(self.items[new_len..], undefined); |
| 384 | self.items.len = new_len; | 412 | self.items.len = new_len; |
| ... | @@ -387,12 +415,15 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -387,12 +415,15 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 387 | /// Reduce length to 0. | 415 | /// Reduce length to 0. |
| 388 | /// Invalidates all element pointers. | 416 | /// Invalidates all element pointers. |
| 389 | pub fn clearRetainingCapacity(self: *Self) void { | 417 | pub fn clearRetainingCapacity(self: *Self) void { |
| | 418 | self.pointer_stability.lock(); |
| | 419 | defer self.pointer_stability.unlock(); |
| 390 | @memset(self.items, undefined); | 420 | @memset(self.items, undefined); |
| 391 | self.items.len = 0; | 421 | self.items.len = 0; |
| 392 | } | 422 | } |
| 393 | | 423 | |
| 394 | /// Invalidates all element pointers. | 424 | /// Invalidates all element pointers. |
| 395 | pub fn clearAndFree(self: *Self) void { | 425 | pub fn clearAndFree(self: *Self) void { |
| | 426 | self.pointer_stability.assertUnlocked(); |
| 396 | self.allocator.free(self.allocatedSlice()); | 427 | self.allocator.free(self.allocatedSlice()); |
| 397 | self.items.len = 0; | 428 | self.items.len = 0; |
| 398 | self.capacity = 0; | 429 | self.capacity = 0; |
| ... | @@ -418,6 +449,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -418,6 +449,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 418 | /// modify the array so that it can hold exactly `new_capacity` items. | 449 | /// modify the array so that it can hold exactly `new_capacity` items. |
| 419 | /// Invalidates element pointers if additional memory is needed. | 450 | /// Invalidates element pointers if additional memory is needed. |
| 420 | pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void { | 451 | pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void { |
| | 452 | self.pointer_stability.lock(); |
| | 453 | defer self.pointer_stability.unlock(); |
| | 454 | |
| 421 | if (@sizeOf(T) == 0) { | 455 | if (@sizeOf(T) == 0) { |
| 422 | self.capacity = math.maxInt(usize); | 456 | self.capacity = math.maxInt(usize); |
| 423 | return; | 457 | return; |
| ... | @@ -523,6 +557,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type | ... | @@ -523,6 +557,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 523 | /// Invalidates element pointers to the removed element, if any. | 557 | /// Invalidates element pointers to the removed element, if any. |
| 524 | pub fn pop(self: *Self) ?T { | 558 | pub fn pop(self: *Self) ?T { |
| 525 | if (self.items.len == 0) return null; | 559 | if (self.items.len == 0) return null; |
| | 560 | self.pointer_stability.lock(); |
| | 561 | defer self.pointer_stability.unlock(); |
| 526 | const val = self.items[self.items.len - 1]; | 562 | const val = self.items[self.items.len - 1]; |
| 527 | self.items[self.items.len - 1] = undefined; | 563 | self.items[self.items.len - 1] = undefined; |
| 528 | self.items.len -= 1; | 564 | self.items.len -= 1; |
| ... | @@ -584,6 +620,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -584,6 +620,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 584 | /// additional memory. | 620 | /// additional memory. |
| 585 | capacity: usize, | 621 | capacity: usize, |
| 586 | | 622 | |
| | 623 | /// Used to detect memory safety violations. |
| | 624 | pointer_stability: debug.SafetyLock = .{}, |
| | 625 | |
| 587 | /// An ArrayList containing no elements. | 626 | /// An ArrayList containing no elements. |
| 588 | pub const empty: Self = .{ | 627 | pub const empty: Self = .{ |
| 589 | .items = &.{}, | 628 | .items = &.{}, |
| ... | @@ -618,10 +657,28 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -618,10 +657,28 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 618 | | 657 | |
| 619 | /// Release all allocated memory. | 658 | /// Release all allocated memory. |
| 620 | pub fn deinit(self: *Self, gpa: Allocator) void { | 659 | pub fn deinit(self: *Self, gpa: Allocator) void { |
| | 660 | self.pointer_stability.assertUnlocked(); |
| 621 | gpa.free(self.allocatedSlice()); | 661 | gpa.free(self.allocatedSlice()); |
| 622 | self.* = undefined; | 662 | self.* = undefined; |
| 623 | } | 663 | } |
| 624 | | 664 | |
| | 665 | /// Puts the unmanaged array list into a state where any method call that would |
| | 666 | /// cause an existing value pointer to become invalidated will |
| | 667 | /// instead trigger an assertion. |
| | 668 | /// |
| | 669 | /// An additional call to `lockPointers` in such state also triggers an |
| | 670 | /// assertion. |
| | 671 | /// |
| | 672 | /// `unlockPointers` returns the unmanaged array list to the previous state. |
| | 673 | pub fn lockPointers(self: *Self) void { |
| | 674 | self.pointer_stability.lock(); |
| | 675 | } |
| | 676 | |
| | 677 | /// Undoes a call to `lockPointers`. |
| | 678 | pub fn unlockPointers(self: *Self) void { |
| | 679 | self.pointer_stability.unlock(); |
| | 680 | } |
| | 681 | |
| 625 | /// Convert this list into an analogous memory-managed one. | 682 | /// Convert this list into an analogous memory-managed one. |
| 626 | /// The returned list has ownership of the underlying memory. | 683 | /// The returned list has ownership of the underlying memory. |
| 627 | pub fn toManaged(self: *Self, gpa: Allocator) AlignedManaged(T, alignment) { | 684 | pub fn toManaged(self: *Self, gpa: Allocator) AlignedManaged(T, alignment) { |
| ... | @@ -718,6 +775,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -718,6 +775,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 718 | /// | 775 | /// |
| 719 | /// Asserts that the index is in bounds or equal to the length. | 776 | /// Asserts that the index is in bounds or equal to the length. |
| 720 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { | 777 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { |
| | 778 | self.pointer_stability.lock(); |
| | 779 | defer self.pointer_stability.unlock(); |
| | 780 | |
| 721 | assert(self.items.len < self.capacity); | 781 | assert(self.items.len < self.capacity); |
| 722 | self.items.len += 1; | 782 | self.items.len += 1; |
| 723 | | 783 | |
| ... | @@ -763,11 +823,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -763,11 +823,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 763 | /// `undefined` values. Returns a slice pointing to the newly allocated | 823 | /// `undefined` values. Returns a slice pointing to the newly allocated |
| 764 | /// elements, which becomes invalid after various `ArrayList` | 824 | /// elements, which becomes invalid after various `ArrayList` |
| 765 | /// operations. | 825 | /// operations. |
| 766 | /// Invalidates pre-existing pointers to elements at and after `index`, but | | |
| 767 | /// does not invalidate any before that. | | |
| 768 | /// Asserts that the list has capacity for the additional items. | 826 | /// Asserts that the list has capacity for the additional items. |
| 769 | /// Asserts that the index is in bounds or equal to the length. | 827 | /// Asserts that the index is in bounds or equal to the length. |
| 770 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { | 828 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| | 829 | self.pointer_stability.lock(); |
| | 830 | defer self.pointer_stability.unlock(); |
| | 831 | |
| 771 | const new_len = self.items.len + count; | 832 | const new_len = self.items.len + count; |
| 772 | assert(self.capacity >= new_len); | 833 | assert(self.capacity >= new_len); |
| 773 | const to_move = self.items[index..]; | 834 | const to_move = self.items[index..]; |
| ... | @@ -783,9 +844,6 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -783,9 +844,6 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 783 | /// allocated elements, which becomes invalid after various `ArrayList` | 844 | /// allocated elements, which becomes invalid after various `ArrayList` |
| 784 | /// operations. | 845 | /// operations. |
| 785 | /// | 846 | /// |
| 786 | /// Invalidates pre-existing pointers to elements at and after `index`, but | | |
| 787 | /// does not invalidate any before that. | | |
| 788 | /// | | |
| 789 | /// If the list lacks unused capacity for the additional items, returns | 847 | /// If the list lacks unused capacity for the additional items, returns |
| 790 | /// `error.OutOfMemory`. | 848 | /// `error.OutOfMemory`. |
| 791 | /// | 849 | /// |
| ... | @@ -967,6 +1025,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -967,6 +1025,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 967 | /// This operation is O(1). | 1025 | /// This operation is O(1). |
| 968 | /// Asserts that the index is in bounds. | 1026 | /// Asserts that the index is in bounds. |
| 969 | pub fn swapRemove(self: *Self, i: usize) T { | 1027 | pub fn swapRemove(self: *Self, i: usize) T { |
| | 1028 | self.pointer_stability.lock(); |
| | 1029 | defer self.pointer_stability.unlock(); |
| 970 | const val = self.items[i]; | 1030 | const val = self.items[i]; |
| 971 | self.items[i] = self.items[self.items.len - 1]; | 1031 | self.items[i] = self.items[self.items.len - 1]; |
| 972 | self.items[self.items.len - 1] = undefined; | 1032 | self.items[self.items.len - 1] = undefined; |
| ... | @@ -1128,6 +1188,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -1128,6 +1188,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1128 | /// Asserts that the new length is less than or equal to the previous length. | 1188 | /// Asserts that the new length is less than or equal to the previous length. |
| 1129 | /// If succeds capacity is guaranteed to be equal to the length. | 1189 | /// If succeds capacity is guaranteed to be equal to the length. |
| 1130 | pub fn shrinkAndFreePrecise(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void { | 1190 | pub fn shrinkAndFreePrecise(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void { |
| | 1191 | self.pointer_stability.lock(); |
| | 1192 | defer self.pointer_stability.unlock(); |
| 1131 | assert(new_len <= self.items.len); | 1193 | assert(new_len <= self.items.len); |
| 1132 | | 1194 | |
| 1133 | if (@sizeOf(T) == 0) { | 1195 | if (@sizeOf(T) == 0) { |
| ... | @@ -1181,6 +1243,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -1181,6 +1243,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1181 | /// Keeps capacity the same. | 1243 | /// Keeps capacity the same. |
| 1182 | /// Asserts that the new length is less than or equal to the previous length. | 1244 | /// Asserts that the new length is less than or equal to the previous length. |
| 1183 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | 1245 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| | 1246 | self.pointer_stability.lock(); |
| | 1247 | defer self.pointer_stability.unlock(); |
| | 1248 | |
| 1184 | assert(new_len <= self.items.len); | 1249 | assert(new_len <= self.items.len); |
| 1185 | @memset(self.items[new_len..], undefined); | 1250 | @memset(self.items[new_len..], undefined); |
| 1186 | self.items.len = new_len; | 1251 | self.items.len = new_len; |
| ... | @@ -1189,12 +1254,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -1189,12 +1254,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1189 | /// Reduce length to 0. | 1254 | /// Reduce length to 0. |
| 1190 | /// Invalidates all element pointers. | 1255 | /// Invalidates all element pointers. |
| 1191 | pub fn clearRetainingCapacity(self: *Self) void { | 1256 | pub fn clearRetainingCapacity(self: *Self) void { |
| | 1257 | self.pointer_stability.lock(); |
| | 1258 | defer self.pointer_stability.unlock(); |
| 1192 | @memset(self.items, undefined); | 1259 | @memset(self.items, undefined); |
| 1193 | self.items.len = 0; | 1260 | self.items.len = 0; |
| 1194 | } | 1261 | } |
| 1195 | | 1262 | |
| 1196 | /// Invalidates all element pointers. | 1263 | /// Invalidates all element pointers. |
| 1197 | pub fn clearAndFree(self: *Self, gpa: Allocator) void { | 1264 | pub fn clearAndFree(self: *Self, gpa: Allocator) void { |
| | 1265 | self.pointer_stability.lock(); |
| | 1266 | defer self.pointer_stability.unlock(); |
| 1198 | gpa.free(self.allocatedSlice()); | 1267 | gpa.free(self.allocatedSlice()); |
| 1199 | self.items.len = 0; | 1268 | self.items.len = 0; |
| 1200 | self.capacity = 0; | 1269 | self.capacity = 0; |
| ... | @@ -1212,6 +1281,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -1212,6 +1281,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1212 | /// modify the array so that it can hold exactly `new_capacity` items. | 1281 | /// modify the array so that it can hold exactly `new_capacity` items. |
| 1213 | /// Invalidates element pointers if additional memory is needed. | 1282 | /// Invalidates element pointers if additional memory is needed. |
| 1214 | pub fn ensureTotalCapacityPrecise(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { | 1283 | pub fn ensureTotalCapacityPrecise(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { |
| | 1284 | self.pointer_stability.lock(); |
| | 1285 | defer self.pointer_stability.unlock(); |
| | 1286 | |
| 1215 | if (@sizeOf(T) == 0) { | 1287 | if (@sizeOf(T) == 0) { |
| 1216 | self.capacity = math.maxInt(usize); | 1288 | self.capacity = math.maxInt(usize); |
| 1217 | return; | 1289 | return; |
| ... | @@ -1371,6 +1443,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { | ... | @@ -1371,6 +1443,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1371 | /// Invalidates pointers to last element. | 1443 | /// Invalidates pointers to last element. |
| 1372 | pub fn pop(self: *Self) ?T { | 1444 | pub fn pop(self: *Self) ?T { |
| 1373 | if (self.items.len == 0) return null; | 1445 | if (self.items.len == 0) return null; |
| | 1446 | self.pointer_stability.lock(); |
| | 1447 | defer self.pointer_stability.unlock(); |
| | 1448 | |
| 1374 | const val = self.items[self.items.len - 1]; | 1449 | const val = self.items[self.items.len - 1]; |
| 1375 | self.items[self.items.len - 1] = undefined; | 1450 | self.items[self.items.len - 1] = undefined; |
| 1376 | self.items.len -= 1; | 1451 | self.items.len -= 1; |