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;