feature. See also
. The project being documented here (as the example) is the Zig library itself.
SafeAllocator.alloc
fn alloc(ctx: *anyopaque, len: usize, alignment: Alignment, ra: usize) ?[*]u8
File
Code
fn alloc(ctx: *anyopaque, len: usize, alignment: Alignment, ra: usize) ?[*]u8 {
assert(len != 0);
const s: *SafeAllocator = @ptrCast(@alignCast(ctx));
const t = s.acquireThread();
defer t.mutex.unlock();
if (s.isLargeOrOom(len, alignment) catch return null) {
@branchHint(.unlikely);
const entry = s.newAllocEntry(t, ra) catch return null;
const alloc_len = AllocFooter.allocLenLarge(s, len);
const alloc_align = AllocFooter.allocAlign(alignment);
const alloc_ptr = s.backing.rawAlloc(alloc_len, alloc_align, ra) orelse {
freeAllocEntry(t, entry);
return null;
};
const footer = AllocFooter.populate(
@alignCast(alloc_ptr[0..alloc_len]),
len,
alignment,
ra,
true,
false,
.{ .large_entry = entry },
s,
);
entry.* = .fromLargeAlloc(footer);
return alloc_ptr;
}
if (t.fill_bucket) |bucket| {
@branchHint(.likely);
if (s.allocBucket(t, bucket, len, alignment, ra)) |ptr| {
@branchHint(.likely);
return ptr;
}
}
t.fill_bucket = null;
// allocations.
const entry = s.newAllocEntry(t, ra) catch return null;
const bucket: *Bucket = @ptrCast(@alignCast(s.backing.rawAlloc(
s.bucketSize(),
@fromBackingInt(@intCast(s.bucket_size_log2)),
ra,
) orelse {
freeAllocEntry(t, entry);
return null;
}));
bucket.* = .{
.entry = entry,
// first to atomically update these below in allocBucket.
.alloc_count = .{ .filling = true, .n = 0 },
.fill = .{ .at = @sizeOf(Bucket), .last_is_extended = false },
};
entry.* = .fromBucket(bucket);
t.fill_bucket = bucket;
return s.allocBucket(t, bucket, len, alignment, ra);
}