From 658de75500871f28015aa2ff14872eed0410dddf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Feb 2023 15:14:16 -0700 Subject: [PATCH] add std.heap.ThreadSafeAllocator This wraps any allocator and makes it thread-safe by using a mutex. --- lib/std/heap.zig | 1 + lib/std/heap/ThreadSafeAllocator.zig | 45 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 lib/std/heap/ThreadSafeAllocator.zig diff --git a/lib/std/heap.zig b/lib/std/heap.zig index c15e5d0ec2..e2d000f318 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -19,6 +19,7 @@ pub const GeneralPurposeAllocator = @import("heap/general_purpose_allocator.zig" pub const WasmAllocator = @import("heap/WasmAllocator.zig"); pub const WasmPageAllocator = @import("heap/WasmPageAllocator.zig"); pub const PageAllocator = @import("heap/PageAllocator.zig"); +pub const ThreadSafeAllocator = @import("heap/ThreadSafeAllocator.zig"); const memory_pool = @import("heap/memory_pool.zig"); pub const MemoryPool = memory_pool.MemoryPool; diff --git a/lib/std/heap/ThreadSafeAllocator.zig b/lib/std/heap/ThreadSafeAllocator.zig new file mode 100644 index 0000000000..fe10eb2fdb --- /dev/null +++ b/lib/std/heap/ThreadSafeAllocator.zig @@ -0,0 +1,45 @@ +//! Wraps a non-thread-safe allocator and makes it thread-safe. + +child_allocator: Allocator, +mutex: std.Thread.Mutex = .{}, + +pub fn allocator(self: *ThreadSafeAllocator) Allocator { + return .{ + .ptr = self, + .vtable = &.{ + .alloc = alloc, + .resize = resize, + .free = free, + }, + }; +} + +fn alloc(ctx: *anyopaque, n: usize, log2_ptr_align: u8, ra: usize) ?[*]u8 { + const self = @ptrCast(*ThreadSafeAllocator, @alignCast(@alignOf(ThreadSafeAllocator), ctx)); + self.mutex.lock(); + defer self.mutex.unlock(); + + return self.child_allocator.rawAlloc(n, log2_ptr_align, ra); +} + +fn resize(ctx: *anyopaque, buf: []u8, log2_buf_align: u8, new_len: usize, ret_addr: usize) bool { + const self = @ptrCast(*ThreadSafeAllocator, @alignCast(@alignOf(ThreadSafeAllocator), ctx)); + + self.mutex.lock(); + defer self.mutex.unlock(); + + return self.child_allocator.rawResize(buf, log2_buf_align, new_len, ret_addr); +} + +fn free(ctx: *anyopaque, buf: []u8, log2_buf_align: u8, ret_addr: usize) void { + const self = @ptrCast(*ThreadSafeAllocator, @alignCast(@alignOf(ThreadSafeAllocator), ctx)); + + self.mutex.lock(); + defer self.mutex.unlock(); + + return self.child_allocator.rawFree(buf, log2_buf_align, ret_addr); +} + +const std = @import("../std.zig"); +const ThreadSafeAllocator = @This(); +const Allocator = std.mem.Allocator;