Fix parallel stack bugs

This commit is contained in:
kayomn 2025-08-27 17:51:22 +01:00
parent 9b0368a568
commit 3ddf351a08

View File

@ -61,7 +61,10 @@ fn Generic(comptime Item: type, comptime Storage: type) type {
pub fn pushAll(self: *Self, items: []const Item) bool { pub fn pushAll(self: *Self, items: []const Item) bool {
const new_len = self.items.len + items.len; const new_len = self.items.len + items.len;
if (new_len < self.cap) { if (new_len > self.items.cap) {
return false;
}
const index = self.items.len; const index = self.items.len;
self.items.len = new_len; self.items.len = new_len;
@ -71,9 +74,6 @@ fn Generic(comptime Item: type, comptime Storage: type) type {
return true; return true;
} }
return false;
}
pub fn pushGrow(self: *Self, allocator: std.mem.Allocator, item: Item) std.mem.Allocator.Error!void { pub fn pushGrow(self: *Self, allocator: std.mem.Allocator, item: Item) std.mem.Allocator.Error!void {
if (self.isFull()) { if (self.isFull()) {
try self.items.grow(allocator, @max(1, self.items.cap)); try self.items.grow(allocator, @max(1, self.items.cap));
@ -99,6 +99,16 @@ fn Generic(comptime Item: type, comptime Storage: type) type {
return true; return true;
} }
pub fn set(self: *Self, item: Item) bool {
if (self.isEmpty()) {
return false;
}
std.debug.assert(self.items.set(self.items.len - 1, item));
return true;
}
}; };
} }
@ -109,8 +119,7 @@ pub fn Parallel(comptime Item: type) type {
}; };
const item_align = @alignOf(Item); const item_align = @alignOf(Item);
const item_size = @sizeOf(usize); const item_size = @sizeOf(Item);
const byte_size = @sizeOf(u8);
return Generic(Item, struct { return Generic(Item, struct {
ptr: [*]align(item_align) u8 = undefined, ptr: [*]align(item_align) u8 = undefined,
@ -130,7 +139,7 @@ pub fn Parallel(comptime Item: type) type {
} }
pub fn get(self: Self, index: usize) ?Item { pub fn get(self: Self, index: usize) ?Item {
if (index >= self.cap) { if (index >= self.len) {
return null; return null;
} }
@ -139,29 +148,52 @@ pub fn Parallel(comptime Item: type) type {
inline for (item_fields) |item_field| { inline for (item_fields) |item_field| {
@field(item, item_field.name) = @as([*]item_field.type, @ptrCast(@alignCast(ptr)))[index]; @field(item, item_field.name) = @as([*]item_field.type, @ptrCast(@alignCast(ptr)))[index];
ptr += @sizeOf(item_field.type) * self.len; ptr += @sizeOf(item_field.type) * self.cap;
} }
return item; return item;
} }
pub fn grow(self: *Self, allocator: std.mem.Allocator, amount: usize) std.mem.Allocator.Error!void { pub fn grow(self: *Self, allocator: std.mem.Allocator, amount: usize) std.mem.Allocator.Error!void {
const new_cap = std.math.cast(u32, @as(usize, self.cap + amount)) orelse { const old_cap = self.cap;
const new_cap = std.math.cast(u32, @as(usize, old_cap) + amount) orelse {
return error.OutOfMemory; return error.OutOfMemory;
}; };
const reallocation = try allocator.alignedAlloc(u8, item_align, byte_size * new_cap); if (new_cap != 0) {
const len_in_bytes = byte_size * self.len; const new_allocation = try allocator.alignedAlloc(u8, item_align, item_size * new_cap);
@memcpy(reallocation[0..len_in_bytes], self.ptr[0..len_in_bytes]); errdefer {
allocator.free(self.ptr[0 .. byte_size * self.cap]); allocator.free(new_allocation);
}
self.ptr = reallocation.ptr; if (old_cap != 0) {
self.cap = @intCast(new_cap); var old_ptr_offset: usize = 0;
var new_ptr_offset: usize = 0;
inline for (item_fields) |field| {
const FieldType = field.type;
const old_field_ptr: [*]const FieldType = @ptrCast(@alignCast(self.ptr + old_ptr_offset));
const new_field_ptr: [*]FieldType = @ptrCast(@alignCast(new_allocation.ptr + new_ptr_offset));
@memcpy(new_field_ptr[0..self.len], old_field_ptr[0..self.len]);
old_ptr_offset += @sizeOf(FieldType) * old_cap;
new_ptr_offset += @sizeOf(FieldType) * new_cap;
}
// Free the old allocation
allocator.free(self.ptr[0 .. item_size * old_cap]);
}
self.ptr = new_allocation.ptr;
self.cap = new_cap;
}
} }
pub fn set(self: Self, index: usize, item: Item) bool { pub fn set(self: Self, index: usize, item: Item) bool {
if (index >= self.cap) { if (index >= self.len) {
return false; return false;
} }
@ -169,7 +201,7 @@ pub fn Parallel(comptime Item: type) type {
inline for (item_fields) |item_field| { inline for (item_fields) |item_field| {
@as([*]item_field.type, @ptrCast(@alignCast(ptr)))[index] = @field(item, item_field.name); @as([*]item_field.type, @ptrCast(@alignCast(ptr)))[index] = @field(item, item_field.name);
ptr += @sizeOf(item_field.type) * self.len; ptr += @sizeOf(item_field.type) * self.cap;
} }
return true; return true;
@ -180,7 +212,7 @@ pub fn Parallel(comptime Item: type) type {
var ptr: [*]u8 = self.ptr; var ptr: [*]u8 = self.ptr;
inline for (item_fields[0..field_index]) |item_field| { inline for (item_fields[0..field_index]) |item_field| {
ptr += @sizeOf(item_field.type) * self.len; ptr += @sizeOf(item_field.type) * self.cap;
} }
return @as([*]item_fields[field_index].type, @ptrCast(@alignCast(ptr)))[0..self.len]; return @as([*]item_fields[field_index].type, @ptrCast(@alignCast(ptr)))[0..self.len];