authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-03 21:07:49-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-06 14:23:23-08:00
logf1717777a2ce12905f86e75a11ff6388332d6926
tree0bcfecb5776ba8266ab205cef72b1ac07b30f5e7
parent0d8166be3f7e1cc2a2200956155ed5a8792614b8

std.heap: delete LoggingAllocator and friends

I don't think these belong in std, at least not in their current form. If someone wants to add these back I'd like to review the patch before it lands. Reverts 629e2e784495dd8ac91493fa7bb11e1772698e42

4 files changed, 0 insertions(+), 329 deletions(-)

lib/std/heap.zig-8
......@@ -8,11 +8,6 @@ const c = std.c;
88const Allocator = std.mem.Allocator;
99const windows = std.os.windows;
1010
11pub const LoggingAllocator = @import("heap/logging_allocator.zig").LoggingAllocator;
12pub const loggingAllocator = @import("heap/logging_allocator.zig").loggingAllocator;
13pub const ScopedLoggingAllocator = @import("heap/logging_allocator.zig").ScopedLoggingAllocator;
14pub const LogToWriterAllocator = @import("heap/log_to_writer_allocator.zig").LogToWriterAllocator;
15pub const logToWriterAllocator = @import("heap/log_to_writer_allocator.zig").logToWriterAllocator;
1611pub const ArenaAllocator = @import("heap/arena_allocator.zig").ArenaAllocator;
1712pub const GeneralPurposeAllocatorConfig = @import("heap/general_purpose_allocator.zig").Config;
1813pub const GeneralPurposeAllocator = @import("heap/general_purpose_allocator.zig").GeneralPurposeAllocator;
......@@ -1062,9 +1057,6 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) {
10621057};
10631058
10641059test {
1065 _ = LoggingAllocator;
1066 _ = LogToWriterAllocator;
1067 _ = ScopedLoggingAllocator;
10681060 _ = @import("heap/memory_pool.zig");
10691061 _ = ArenaAllocator;
10701062 _ = GeneralPurposeAllocator;
lib/std/heap/log_to_writer_allocator.zig deleted-145
......@@ -1,145 +0,0 @@
1const std = @import("../std.zig");
2const Allocator = std.mem.Allocator;
3
4/// This allocator is used in front of another allocator and logs to the provided writer
5/// on every call to the allocator. Writer errors are ignored.
6pub fn LogToWriterAllocator(comptime Writer: type) type {
7 return struct {
8 parent_allocator: Allocator,
9 writer: Writer,
10
11 const Self = @This();
12
13 pub fn init(parent_allocator: Allocator, writer: Writer) Self {
14 return Self{
15 .parent_allocator = parent_allocator,
16 .writer = writer,
17 };
18 }
19
20 pub fn allocator(self: *Self) Allocator {
21 return .{
22 .ptr = self,
23 .vtable = &.{
24 .alloc = alloc,
25 .resize = resize,
26 .remap = remap,
27 .free = free,
28 },
29 };
30 }
31
32 fn alloc(
33 ctx: *anyopaque,
34 len: usize,
35 alignment: std.mem.Alignment,
36 ra: usize,
37 ) ?[*]u8 {
38 const self: *Self = @ptrCast(@alignCast(ctx));
39 self.writer.print("alloc : {}", .{len}) catch {};
40 const result = self.parent_allocator.rawAlloc(len, alignment, ra);
41 if (result != null) {
42 self.writer.print(" success!\n", .{}) catch {};
43 } else {
44 self.writer.print(" failure!\n", .{}) catch {};
45 }
46 return result;
47 }
48
49 fn resize(
50 ctx: *anyopaque,
51 buf: []u8,
52 alignment: std.mem.Alignment,
53 new_len: usize,
54 ra: usize,
55 ) bool {
56 const self: *Self = @ptrCast(@alignCast(ctx));
57 if (new_len <= buf.len) {
58 self.writer.print("shrink: {} to {}\n", .{ buf.len, new_len }) catch {};
59 } else {
60 self.writer.print("expand: {} to {}", .{ buf.len, new_len }) catch {};
61 }
62
63 if (self.parent_allocator.rawResize(buf, alignment, new_len, ra)) {
64 if (new_len > buf.len) {
65 self.writer.print(" success!\n", .{}) catch {};
66 }
67 return true;
68 }
69
70 std.debug.assert(new_len > buf.len);
71 self.writer.print(" failure!\n", .{}) catch {};
72 return false;
73 }
74
75 fn remap(
76 ctx: *anyopaque,
77 buf: []u8,
78 alignment: std.mem.Alignment,
79 new_len: usize,
80 ra: usize,
81 ) ?[*]u8 {
82 const self: *Self = @ptrCast(@alignCast(ctx));
83 if (new_len <= buf.len) {
84 self.writer.print("shrink: {} to {}\n", .{ buf.len, new_len }) catch {};
85 } else {
86 self.writer.print("expand: {} to {}", .{ buf.len, new_len }) catch {};
87 }
88
89 if (self.parent_allocator.rawRemap(buf, alignment, new_len, ra)) |new_memory| {
90 if (new_len > buf.len) {
91 self.writer.print(" success!\n", .{}) catch {};
92 }
93 return new_memory;
94 }
95
96 std.debug.assert(new_len > buf.len);
97 self.writer.print(" failure!\n", .{}) catch {};
98 return null;
99 }
100
101 fn free(
102 ctx: *anyopaque,
103 buf: []u8,
104 alignment: std.mem.Alignment,
105 ra: usize,
106 ) void {
107 const self: *Self = @ptrCast(@alignCast(ctx));
108 self.writer.print("free : {}\n", .{buf.len}) catch {};
109 self.parent_allocator.rawFree(buf, alignment, ra);
110 }
111 };
112}
113
114/// This allocator is used in front of another allocator and logs to the provided writer
115/// on every call to the allocator. Writer errors are ignored.
116pub fn logToWriterAllocator(
117 parent_allocator: Allocator,
118 writer: anytype,
119) LogToWriterAllocator(@TypeOf(writer)) {
120 return LogToWriterAllocator(@TypeOf(writer)).init(parent_allocator, writer);
121}
122
123test "LogToWriterAllocator" {
124 var log_buf: [255]u8 = undefined;
125 var fbs = std.io.fixedBufferStream(&log_buf);
126
127 var allocator_buf: [10]u8 = undefined;
128 var fixedBufferAllocator = std.mem.validationWrap(std.heap.FixedBufferAllocator.init(&allocator_buf));
129 var allocator_state = logToWriterAllocator(fixedBufferAllocator.allocator(), fbs.writer());
130 const allocator = allocator_state.allocator();
131
132 var a = try allocator.alloc(u8, 10);
133 try std.testing.expect(allocator.resize(a, 5));
134 a = a[0..5];
135 try std.testing.expect(!allocator.resize(a, 20));
136 allocator.free(a);
137
138 try std.testing.expectEqualSlices(u8,
139 \\alloc : 10 success!
140 \\shrink: 10 to 5
141 \\expand: 5 to 20 failure!
142 \\free : 5
143 \\
144 , fbs.getWritten());
145}
lib/std/heap/logging_allocator.zig deleted-133
......@@ -1,133 +0,0 @@
1const std = @import("../std.zig");
2const Allocator = std.mem.Allocator;
3
4/// This allocator is used in front of another allocator and logs to `std.log`
5/// on every call to the allocator.
6/// For logging to a `std.io.Writer` see `std.heap.LogToWriterAllocator`
7pub fn LoggingAllocator(
8 comptime success_log_level: std.log.Level,
9 comptime failure_log_level: std.log.Level,
10) type {
11 return ScopedLoggingAllocator(.default, success_log_level, failure_log_level);
12}
13
14/// This allocator is used in front of another allocator and logs to `std.log`
15/// with the given scope on every call to the allocator.
16/// For logging to a `std.io.Writer` see `std.heap.LogToWriterAllocator`
17pub fn ScopedLoggingAllocator(
18 comptime scope: @Type(.enum_literal),
19 comptime success_log_level: std.log.Level,
20 comptime failure_log_level: std.log.Level,
21) type {
22 const log = std.log.scoped(scope);
23
24 return struct {
25 parent_allocator: Allocator,
26
27 const Self = @This();
28
29 pub fn init(parent_allocator: Allocator) Self {
30 return .{
31 .parent_allocator = parent_allocator,
32 };
33 }
34
35 pub fn allocator(self: *Self) Allocator {
36 return .{
37 .ptr = self,
38 .vtable = &.{
39 .alloc = alloc,
40 .resize = resize,
41 .free = free,
42 },
43 };
44 }
45
46 // This function is required as the `std.log.log` function is not public
47 inline fn logHelper(comptime log_level: std.log.Level, comptime format: []const u8, args: anytype) void {
48 switch (log_level) {
49 .err => log.err(format, args),
50 .warn => log.warn(format, args),
51 .info => log.info(format, args),
52 .debug => log.debug(format, args),
53 }
54 }
55
56 fn alloc(
57 ctx: *anyopaque,
58 len: usize,
59 log2_ptr_align: u8,
60 ra: usize,
61 ) ?[*]u8 {
62 const self: *Self = @ptrCast(@alignCast(ctx));
63 const result = self.parent_allocator.rawAlloc(len, log2_ptr_align, ra);
64 if (result != null) {
65 logHelper(
66 success_log_level,
67 "alloc - success - len: {}, ptr_align: {}",
68 .{ len, log2_ptr_align },
69 );
70 } else {
71 logHelper(
72 failure_log_level,
73 "alloc - failure: OutOfMemory - len: {}, ptr_align: {}",
74 .{ len, log2_ptr_align },
75 );
76 }
77 return result;
78 }
79
80 fn resize(
81 ctx: *anyopaque,
82 buf: []u8,
83 log2_buf_align: u8,
84 new_len: usize,
85 ra: usize,
86 ) bool {
87 const self: *Self = @ptrCast(@alignCast(ctx));
88 if (self.parent_allocator.rawResize(buf, log2_buf_align, new_len, ra)) {
89 if (new_len <= buf.len) {
90 logHelper(
91 success_log_level,
92 "shrink - success - {} to {}, buf_align: {}",
93 .{ buf.len, new_len, log2_buf_align },
94 );
95 } else {
96 logHelper(
97 success_log_level,
98 "expand - success - {} to {}, buf_align: {}",
99 .{ buf.len, new_len, log2_buf_align },
100 );
101 }
102
103 return true;
104 }
105
106 std.debug.assert(new_len > buf.len);
107 logHelper(
108 failure_log_level,
109 "expand - failure - {} to {}, buf_align: {}",
110 .{ buf.len, new_len, log2_buf_align },
111 );
112 return false;
113 }
114
115 fn free(
116 ctx: *anyopaque,
117 buf: []u8,
118 log2_buf_align: u8,
119 ra: usize,
120 ) void {
121 const self: *Self = @ptrCast(@alignCast(ctx));
122 self.parent_allocator.rawFree(buf, log2_buf_align, ra);
123 logHelper(success_log_level, "free - len: {}", .{buf.len});
124 }
125 };
126}
127
128/// This allocator is used in front of another allocator and logs to `std.log`
129/// on every call to the allocator.
130/// For logging to a `std.io.Writer` see `std.heap.LogToWriterAllocator`
131pub fn loggingAllocator(parent_allocator: Allocator) LoggingAllocator(.debug, .err) {
132 return LoggingAllocator(.debug, .err).init(parent_allocator);
133}
test/compare_output.zig-43
......@@ -493,49 +493,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
493493 \\
494494 );
495495
496 // It is required to override the log function in order to print to stdout instead of stderr
497 cases.add("std.heap.LoggingAllocator logs to std.log",
498 \\const std = @import("std");
499 \\
500 \\pub const std_options: std.Options = .{
501 \\ .log_level = .debug,
502 \\ .logFn = log,
503 \\};
504 \\
505 \\pub fn main() !void {
506 \\ var allocator_buf: [10]u8 = undefined;
507 \\ const fba = std.heap.FixedBufferAllocator.init(&allocator_buf);
508 \\ var fba_wrapped = std.mem.validationWrap(fba);
509 \\ var logging_allocator = std.heap.loggingAllocator(fba_wrapped.allocator());
510 \\ const allocator = logging_allocator.allocator();
511 \\
512 \\ var a = try allocator.alloc(u8, 10);
513 \\ try std.testing.expect(allocator.resize(a, 5));
514 \\ a = a[0..5];
515 \\ try std.testing.expect(a.len == 5);
516 \\ try std.testing.expect(!allocator.resize(a, 20));
517 \\ allocator.free(a);
518 \\}
519 \\
520 \\pub fn log(
521 \\ comptime level: std.log.Level,
522 \\ comptime scope: @TypeOf(.EnumLiteral),
523 \\ comptime format: []const u8,
524 \\ args: anytype,
525 \\) void {
526 \\ const level_txt = comptime level.asText();
527 \\ const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
528 \\ const stdout = std.io.getStdOut().writer();
529 \\ nosuspend stdout.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return;
530 \\}
531 ,
532 \\debug: alloc - success - len: 10, ptr_align: 0
533 \\debug: shrink - success - 10 to 5, buf_align: 0
534 \\error: expand - failure - 5 to 20, buf_align: 0
535 \\debug: free - len: 5
536 \\
537 );
538
539496 cases.add("valid carriage return example", "const io = @import(\"std\").io;\r\n" ++ // Testing CRLF line endings are valid
540497 "\r\n" ++
541498 "pub \r fn main() void {\r\n" ++ // Testing isolated carriage return as whitespace is valid