master
 1//! Wraps a non-thread-safe allocator and makes it thread-safe.
 2
 3child_allocator: Allocator,
 4mutex: std.Thread.Mutex = .{},
 5
 6pub fn allocator(self: *ThreadSafeAllocator) Allocator {
 7    return .{
 8        .ptr = self,
 9        .vtable = &.{
10            .alloc = alloc,
11            .resize = resize,
12            .remap = remap,
13            .free = free,
14        },
15    };
16}
17
18fn alloc(ctx: *anyopaque, n: usize, alignment: std.mem.Alignment, ra: usize) ?[*]u8 {
19    const self: *ThreadSafeAllocator = @ptrCast(@alignCast(ctx));
20    self.mutex.lock();
21    defer self.mutex.unlock();
22
23    return self.child_allocator.rawAlloc(n, alignment, ra);
24}
25
26fn resize(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) bool {
27    const self: *ThreadSafeAllocator = @ptrCast(@alignCast(ctx));
28
29    self.mutex.lock();
30    defer self.mutex.unlock();
31
32    return self.child_allocator.rawResize(buf, alignment, new_len, ret_addr);
33}
34
35fn remap(context: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, return_address: usize) ?[*]u8 {
36    const self: *ThreadSafeAllocator = @ptrCast(@alignCast(context));
37
38    self.mutex.lock();
39    defer self.mutex.unlock();
40
41    return self.child_allocator.rawRemap(memory, alignment, new_len, return_address);
42}
43
44fn free(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, ret_addr: usize) void {
45    const self: *ThreadSafeAllocator = @ptrCast(@alignCast(ctx));
46
47    self.mutex.lock();
48    defer self.mutex.unlock();
49
50    return self.child_allocator.rawFree(buf, alignment, ret_addr);
51}
52
53const std = @import("../std.zig");
54const ThreadSafeAllocator = @This();
55const Allocator = std.mem.Allocator;