aboutsummaryrefslogtreecommitdiff
path: root/src/galloc.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/galloc.zig')
-rw-r--r--src/galloc.zig77
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);
+}