mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 15:42:49 +00:00
ceb0a632cf
closes #13535
134 lines
4.5 KiB
Zig
134 lines
4.5 KiB
Zig
const std = @import("../std.zig");
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
/// This allocator is used in front of another allocator and logs to `std.log`
|
|
/// on every call to the allocator.
|
|
/// For logging to a `std.io.Writer` see `std.heap.LogToWriterAllocator`
|
|
pub fn LoggingAllocator(
|
|
comptime success_log_level: std.log.Level,
|
|
comptime failure_log_level: std.log.Level,
|
|
) type {
|
|
return ScopedLoggingAllocator(.default, success_log_level, failure_log_level);
|
|
}
|
|
|
|
/// This allocator is used in front of another allocator and logs to `std.log`
|
|
/// with the given scope on every call to the allocator.
|
|
/// For logging to a `std.io.Writer` see `std.heap.LogToWriterAllocator`
|
|
pub fn ScopedLoggingAllocator(
|
|
comptime scope: @Type(.EnumLiteral),
|
|
comptime success_log_level: std.log.Level,
|
|
comptime failure_log_level: std.log.Level,
|
|
) type {
|
|
const log = std.log.scoped(scope);
|
|
|
|
return struct {
|
|
parent_allocator: Allocator,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn init(parent_allocator: Allocator) Self {
|
|
return .{
|
|
.parent_allocator = parent_allocator,
|
|
};
|
|
}
|
|
|
|
pub fn allocator(self: *Self) Allocator {
|
|
return .{
|
|
.ptr = self,
|
|
.vtable = &.{
|
|
.alloc = alloc,
|
|
.resize = resize,
|
|
.free = free,
|
|
},
|
|
};
|
|
}
|
|
|
|
// This function is required as the `std.log.log` function is not public
|
|
inline fn logHelper(comptime log_level: std.log.Level, comptime format: []const u8, args: anytype) void {
|
|
switch (log_level) {
|
|
.err => log.err(format, args),
|
|
.warn => log.warn(format, args),
|
|
.info => log.info(format, args),
|
|
.debug => log.debug(format, args),
|
|
}
|
|
}
|
|
|
|
fn alloc(
|
|
ctx: *anyopaque,
|
|
len: usize,
|
|
log2_ptr_align: u8,
|
|
ra: usize,
|
|
) ?[*]u8 {
|
|
const self = @ptrCast(*Self, @alignCast(@alignOf(Self), ctx));
|
|
const result = self.parent_allocator.rawAlloc(len, log2_ptr_align, ra);
|
|
if (result != null) {
|
|
logHelper(
|
|
success_log_level,
|
|
"alloc - success - len: {}, ptr_align: {}",
|
|
.{ len, log2_ptr_align },
|
|
);
|
|
} else {
|
|
logHelper(
|
|
failure_log_level,
|
|
"alloc - failure: OutOfMemory - len: {}, ptr_align: {}",
|
|
.{ len, log2_ptr_align },
|
|
);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
fn resize(
|
|
ctx: *anyopaque,
|
|
buf: []u8,
|
|
log2_buf_align: u8,
|
|
new_len: usize,
|
|
ra: usize,
|
|
) bool {
|
|
const self = @ptrCast(*Self, @alignCast(@alignOf(Self), ctx));
|
|
if (self.parent_allocator.rawResize(buf, log2_buf_align, new_len, ra)) {
|
|
if (new_len <= buf.len) {
|
|
logHelper(
|
|
success_log_level,
|
|
"shrink - success - {} to {}, buf_align: {}",
|
|
.{ buf.len, new_len, log2_buf_align },
|
|
);
|
|
} else {
|
|
logHelper(
|
|
success_log_level,
|
|
"expand - success - {} to {}, buf_align: {}",
|
|
.{ buf.len, new_len, log2_buf_align },
|
|
);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std.debug.assert(new_len > buf.len);
|
|
logHelper(
|
|
failure_log_level,
|
|
"expand - failure - {} to {}, buf_align: {}",
|
|
.{ buf.len, new_len, log2_buf_align },
|
|
);
|
|
return false;
|
|
}
|
|
|
|
fn free(
|
|
ctx: *anyopaque,
|
|
buf: []u8,
|
|
log2_buf_align: u8,
|
|
ra: usize,
|
|
) void {
|
|
const self = @ptrCast(*Self, @alignCast(@alignOf(Self), ctx));
|
|
self.parent_allocator.rawFree(buf, log2_buf_align, ra);
|
|
logHelper(success_log_level, "free - len: {}", .{buf.len});
|
|
}
|
|
};
|
|
}
|
|
|
|
/// This allocator is used in front of another allocator and logs to `std.log`
|
|
/// on every call to the allocator.
|
|
/// For logging to a `std.io.Writer` see `std.heap.LogToWriterAllocator`
|
|
pub fn loggingAllocator(parent_allocator: Allocator) LoggingAllocator(.debug, .err) {
|
|
return LoggingAllocator(.debug, .err).init(parent_allocator);
|
|
}
|