-
-
Save ozzyozbourne/0e8eb1f4a84256f676d9237132a74f49 to your computer and use it in GitHub Desktop.
allocates many slices with different sizes with a single allocation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pub fn SlabAllocation(comptime types: []const type) type { | |
| var alignment: usize = 1; | |
| var slices: [types.len]type = undefined; | |
| for (types, 0..) |T, i| { | |
| slices[i] = []T; | |
| alignment = @max(alignment, @alignOf(T)); | |
| } | |
| const out_alignment = alignment; | |
| const Slices = std.meta.Tuple(&slices); | |
| return struct { | |
| blob: []align(out_alignment) u8, | |
| slices: Slices, | |
| pub fn deinit(self: *const @This(), allocator: std.mem.Allocator) void { | |
| allocator.free(self.blob); | |
| } | |
| }; | |
| } | |
| /// allocates many slices with different sizes with a single allocation, usage: | |
| /// ``` | |
| /// const cube_data = try slabAlloc(allocator, &.{ MeshVert, MeshIndex }, .{ 24, 36 }); | |
| /// defer cube_data.deinit(allocator); | |
| /// | |
| /// const verts = cube_data.slices[0]; | |
| /// const indices = cube_data.slices[1]; | |
| /// // ... | |
| /// ``` | |
| pub fn slabAlloc(allocator: std.mem.Allocator, comptime types: []const type, sizes: anytype) !SlabAllocation(types) { | |
| const info = comptime blk: { | |
| const Data = struct { | |
| size: usize, | |
| index: usize, | |
| alignment: usize, | |
| fn lessThan(context: void, lhs: @This(), rhs: @This()) bool { | |
| _ = context; | |
| return lhs.alignment > rhs.alignment; | |
| } | |
| }; | |
| var data: [types.len]Data = undefined; | |
| for (types, 0..) |T, i| { | |
| data[i] = .{ .size = @sizeOf(T), .index = i, .alignment = @alignOf(T) }; | |
| } | |
| std.mem.sort(Data, &data, {}, Data.lessThan); | |
| var alignment: usize = 1; | |
| var indexes: [types.len]usize = undefined; | |
| for (data, 0..) |elem, i| { | |
| indexes[i] = elem.index; | |
| alignment = @max(alignment, elem.alignment); | |
| } | |
| break :blk .{ .indexes = indexes, .alignment = alignment }; | |
| }; | |
| var size: usize = 0; | |
| inline for (types, 0..) |T, i| { | |
| size += sizes[i] * @sizeOf(T); | |
| } | |
| var allocation: SlabAllocation(types) = undefined; | |
| allocation.blob = try allocator.alignedAlloc(u8, @truncate(info.alignment), size); | |
| var offset: usize = 0; | |
| inline for (info.indexes) |i| { | |
| const ptr: [*]types[i] = @ptrCast(@alignCast(allocation.blob.ptr + offset)); | |
| allocation.slices[i] = ptr[0..sizes[i]]; | |
| offset += @sizeOf(types[i]) * sizes[i]; | |
| } | |
| return allocation; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment