diff options
author | Gabriel A. Giovanini <mail@gabrielgio.me> | 2025-02-25 22:51:57 +0100 |
---|---|---|
committer | Gabriel A. Giovanini <mail@gabrielgio.me> | 2025-02-25 23:09:28 +0100 |
commit | d1a1365c517f8733512fa9d4aa830fc279c4f9f5 (patch) | |
tree | 0b017da5be18a67745823ae152f60c826cc9f2ca /src/galloc.zig | |
parent | 10bdf5aea299a638f3763afcc7660a3d88cadcab (diff) | |
download | cerrado-d1a1365c517f8733512fa9d4aa830fc279c4f9f5.tar.gz cerrado-d1a1365c517f8733512fa9d4aa830fc279c4f9f5.tar.bz2 cerrado-d1a1365c517f8733512fa9d4aa830fc279c4f9f5.zip |
feat: Add custom allocator
Diffstat (limited to 'src/galloc.zig')
-rw-r--r-- | src/galloc.zig | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/galloc.zig b/src/galloc.zig new file mode 100644 index 0000000..7cb4480 --- /dev/null +++ b/src/galloc.zig @@ -0,0 +1,77 @@ +const std = @import("std"); +const testing = std.testing; + +pub const GitAllocator = struct { + mutex: std.Thread.Mutex, + alloc: std.mem.Allocator, + allocs: std.AutoArrayHashMap(*anyopaque, []u8) = undefined, + + pub fn init(alloc: std.mem.Allocator) GitAllocator { + return GitAllocator{ + .alloc = alloc, + .allocs = std.AutoArrayHashMap(*anyopaque, []u8).init(alloc), + .mutex = std.Thread.Mutex{}, + }; + } + + fn nalloc(self: *GitAllocator, size: usize) ?*anyopaque { + const frame = self.alloc.alloc(u8, size) catch return null; + self.allocs.put(frame.ptr, frame) catch return null; + return frame.ptr; + } + + pub fn malloc(self: *GitAllocator, size: usize) ?*anyopaque { + self.mutex.lock(); + defer self.mutex.unlock(); + return self.nalloc(size); + } + + pub fn realloc(self: *GitAllocator, nptr: ?*anyopaque, size: usize) ?*anyopaque { + self.mutex.lock(); + defer self.mutex.unlock(); + + const ptr = nptr orelse return self.nalloc(size); + + const frame = self.allocs.get(ptr) orelse return null; + if (!self.allocs.swapRemove(ptr)) { + @panic("failed to remove"); + } + + const new_frame = self.alloc.realloc(frame, size) catch return null; + + self.allocs.put(new_frame.ptr, new_frame) catch return null; + return new_frame.ptr; + } + + pub fn free(self: *GitAllocator, nptr: ?*anyopaque) void { + self.mutex.lock(); + defer self.mutex.unlock(); + + const ptr = nptr orelse return; + + const frame = self.allocs.get(ptr) orelse return; + + defer self.alloc.free(frame); + if (!self.allocs.swapRemove(ptr)) { + @panic("failed to remove"); + } + } + + pub fn deinit(self: *GitAllocator) void { + self.allocs.deinit(); + } +}; + +test "test git allocator" { + var gitAlloc = GitAllocator.init(testing.allocator); + defer gitAlloc.deinit(); + + var ptr = gitAlloc.malloc(2_000); + + try testing.expect(ptr != null); + + ptr = gitAlloc.realloc(ptr, 4_000); + ptr = gitAlloc.realloc(ptr, 1_000); + + gitAlloc.free(ptr); +} |