Skip to content

Instantly share code, notes, and snippets.

@Tetralux
Last active January 18, 2024 13:54
Show Gist options
  • Save Tetralux/1386b1d191cc6d67b66d9ed8bc90e0ae to your computer and use it in GitHub Desktop.
Save Tetralux/1386b1d191cc6d67b66d9ed8bc90e0ae to your computer and use it in GitHub Desktop.
Zig interface example (Allocator)
const Ally = struct {
data: ?*anyopaque,
proc: *const fn(
ally_data: ?*anyopaque,
mode: Mode,
count: usize,
alignment: usize,
old_memory: []u8,
) error{OutOfMemory}![]u8,
fn alloc(ally: Ally, comptime T: type, count: usize) ![]T {
const num_bytes = @sizeOf(T) * count;
if (num_bytes == 0) return &.{};
const buffer = try ally.proc(ally.data, .alloc, num_bytes, @alignOf(T), &.{});
return std.mem.bytesAsSlice([]T, buffer);
}
fn realloc(ally: Ally, buffer: anytype, new_count: usize) ![]std.meta.Child(@TypeOf(buffer)) {
const ElemType = std.meta.Child(@TypeOf(buffer));
const old_bytes = std.mem.sliceAsBytes(buffer);
const new_buffer = try ally.proc(ally.data, .realloc, new_count, @alignOf(ElemType), old_bytes);
const new_elems = std.mem.bytesAsSlice([]ElemType, new_buffer);
@memcpy(new_elems[0..buffer.len], buffer);
return new_elems;
}
fn free(ally: Ally, buffer: anytype) void {
const ElemType = std.meta.Child(@TypeOf(buffer));
const old_bytes = std.mem.sliceAsBytes(buffer);
_ = ally.proc(ally.data, .free, 0, 0, old_bytes) catch return;
}
const Mode = enum {
alloc,
realloc,
free,
};
};
const Arena = struct {
// fields omitted for brevity
fn ally(a: *Arena) Ally {
return .{
.data = a,
.proc = ally_proc,
};
}
fn ally_proc(ally_data: ?*anyopaque, mode: Mode, count: usize, alignment: usize, old_memory: []u8) error{OutOfMemory}![]u8 {
const arena: *Arena = @ptrCast(@alignCast(ally_data.?));
// NOTE: the cast is just in here, instead of making a wrapper proc for it!
switch (mode) {
.alloc => { ... },
.realloc => { ... },
.free => { ... },
}
return error.OutOfMemory;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment