Trailed by [allocs_entry_count]Entry
const Allocs = extern struct
const Allocs = extern struct {
next: ?*Allocs,
comptime {
assert(@alignOf(@This()) == @alignOf(usize));
assert(@sizeOf(@This()) == @sizeOf(usize));
}
fn usizes(a: *Allocs, s: *SafeAllocator) []usize {
return @as([*]usize, @ptrCast(a))[0 .. 1 + s.allocs_entry_count];
}
fn entries(a: *Allocs, s: *SafeAllocator) []Entry {
return @as([*]Entry, @ptrCast(a))[1..][0..s.allocs_entry_count];
}
const Entry = packed struct(usize) {
kind: Kind,
ptr_high: @Int(.unsigned, @bitSizeOf(usize) - 2),
const Kind = enum(u2) { free, bucket, large_alloc };
comptime {
assert(@alignOf(Entry) >= 4);
assert(@alignOf(Bucket) >= 4);
assert(@alignOf(AllocFooter) >= 4);
}
fn fromFree(ptr: ?*Entry) Entry {
return .{
.ptr_high = @intCast(@intFromPtr(ptr) >> 2),
.kind = .free,
};
}
fn fromBucket(ptr: *Bucket) Entry {
return .{
.ptr_high = @intCast(@intFromPtr(ptr) >> 2),
.kind = .bucket,
};
}
fn fromLargeAlloc(ptr: *AllocFooter) Entry {
return .{
.ptr_high = @intCast(@intFromPtr(ptr) >> 2),
.kind = .large_alloc,
};
}
fn toFree(ent: Entry) ?*Entry {
assert(ent.kind == .free);
return @ptrFromInt(@as(usize, ent.ptr_high) << 2);
}
fn toBucket(ent: Entry) *Bucket {
assert(ent.kind == .bucket);
return @ptrFromInt(@as(usize, ent.ptr_high) << 2);
}
fn toLargeAlloc(ent: Entry) *AllocFooter {
assert(ent.kind == .large_alloc);
return @ptrFromInt(@as(usize, ent.ptr_high) << 2);
}
};
}