max_allocator.zig (2977B)
1 const std = @import("std"); 2 3 // Wrapper allocator that counts what the largest amount allocated at any time was from backing_allocator. 4 pub const MaxAllocator = struct { 5 backing_allocator: std.mem.Allocator, 6 currently_allocated: usize = 0, 7 max_allocated: usize = 0, 8 9 pub fn allocator(self: *@This()) std.mem.Allocator { 10 return std.mem.Allocator{ 11 .ptr = self, 12 .vtable = &.{ 13 .alloc = rawAlloc, 14 .resize = rawResize, 15 .free = rawFree, 16 }, 17 }; 18 } 19 20 fn rawAlloc(ctx: *anyopaque, len: usize, ptr_align: u8, ret_addr: usize) ?[*]u8 { 21 var self: *@This() = @alignCast(@ptrCast(ctx)); 22 var res = self.backing_allocator.rawAlloc(len, ptr_align, ret_addr); 23 if (res != null) { 24 self.currently_allocated += len; 25 self.max_allocated = @max(self.currently_allocated, self.max_allocated); 26 } 27 return res; 28 } 29 30 fn rawResize(ctx: *anyopaque, buf: []u8, buf_align: u8, new_len: usize, ret_addr: usize) bool { 31 var self: *@This() = @alignCast(@ptrCast(ctx)); 32 const res = self.backing_allocator.rawResize(buf, buf_align, new_len, ret_addr); 33 if (res) { 34 self.currently_allocated -= buf.len; 35 self.currently_allocated += new_len; 36 self.max_allocated = @max(self.currently_allocated, self.max_allocated); 37 } 38 return res; 39 } 40 41 fn rawFree(ctx: *anyopaque, buf: []u8, buf_align: u8, ret_addr: usize) void { 42 var self: *@This() = @alignCast(@ptrCast(ctx)); 43 self.backing_allocator.rawFree(buf, buf_align, ret_addr); 44 self.currently_allocated -= buf.len; 45 } 46 }; 47 48 pub fn maxAllocator(backing_allocator: std.mem.Allocator) MaxAllocator { 49 return MaxAllocator{ .backing_allocator = backing_allocator }; 50 } 51 52 test { 53 const buflen = 2048; 54 var buf = [_]u8{0} ** buflen; 55 var fba = std.heap.FixedBufferAllocator.init(&buf); 56 var ma = maxAllocator(fba.allocator()); 57 var a = ma.allocator(); 58 var x = try a.alloc(u8, 100); 59 try std.testing.expectEqual(@as(usize, 100), ma.max_allocated); 60 try std.testing.expectEqual(@as(usize, 100), ma.currently_allocated); 61 var y = try a.alloc(u8, 10); 62 try std.testing.expectEqual(@as(usize, 110), ma.max_allocated); 63 try std.testing.expectEqual(@as(usize, 110), ma.currently_allocated); 64 a.free(x); 65 var z = try a.alloc(u8, 50); 66 try std.testing.expectEqual(@as(usize, 110), ma.max_allocated); 67 try std.testing.expectEqual(@as(usize, 60), ma.currently_allocated); 68 69 try std.testing.expect(a.resize(z, 1024)); 70 z.len = 1024; 71 try std.testing.expectEqual(@as(usize, 1034), ma.max_allocated); 72 try std.testing.expectEqual(@as(usize, 1034), ma.currently_allocated); 73 74 a.free(y); 75 a.free(z); 76 77 try std.testing.expectEqual(@as(usize, 1034), ma.max_allocated); 78 try std.testing.expectEqual(@as(usize, 0), ma.currently_allocated); 79 }