Last active
January 18, 2024 13:54
-
-
Save Tetralux/1386b1d191cc6d67b66d9ed8bc90e0ae to your computer and use it in GitHub Desktop.
Zig interface example (Allocator)
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
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