authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-03 21:03:27-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-06 14:23:23-08:00
log0d8166be3f7e1cc2a2200956155ed5a8792614b8
treea772fb858ab7101dd9d2ebbc244d7449b5c4b1f6
parenta4d4e086c59b702c34218105764d4ec491ecc566

std: update to new Allocator API


3 files changed, 105 insertions(+), 66 deletions(-)

lib/std/heap.zig+49-33
...@@ -147,12 +147,12 @@ const CAllocator = struct {...@@ -147,12 +147,12 @@ const CAllocator = struct {
147 return @as(*[*]u8, @ptrFromInt(@intFromPtr(ptr) - @sizeOf(usize)));147 return @as(*[*]u8, @ptrFromInt(@intFromPtr(ptr) - @sizeOf(usize)));
148 }148 }
149149
150 fn alignedAlloc(len: usize, log2_align: u8) ?[*]u8 {150 fn alignedAlloc(len: usize, alignment: mem.Alignment) ?[*]u8 {
151 const alignment = @as(usize, 1) << @as(Allocator.Log2Align, @intCast(log2_align));151 const alignment_bytes = alignment.toByteUnits();
152 if (supports_posix_memalign) {152 if (supports_posix_memalign) {
153 // The posix_memalign only accepts alignment values that are a153 // The posix_memalign only accepts alignment values that are a
154 // multiple of the pointer size154 // multiple of the pointer size
155 const eff_alignment = @max(alignment, @sizeOf(usize));155 const eff_alignment = @max(alignment_bytes, @sizeOf(usize));
156156
157 var aligned_ptr: ?*anyopaque = undefined;157 var aligned_ptr: ?*anyopaque = undefined;
158 if (c.posix_memalign(&aligned_ptr, eff_alignment, len) != 0)158 if (c.posix_memalign(&aligned_ptr, eff_alignment, len) != 0)
...@@ -164,9 +164,9 @@ const CAllocator = struct {...@@ -164,9 +164,9 @@ const CAllocator = struct {
164 // Thin wrapper around regular malloc, overallocate to account for164 // Thin wrapper around regular malloc, overallocate to account for
165 // alignment padding and store the original malloc()'ed pointer before165 // alignment padding and store the original malloc()'ed pointer before
166 // the aligned address.166 // the aligned address.
167 const unaligned_ptr = @as([*]u8, @ptrCast(c.malloc(len + alignment - 1 + @sizeOf(usize)) orelse return null));167 const unaligned_ptr = @as([*]u8, @ptrCast(c.malloc(len + alignment_bytes - 1 + @sizeOf(usize)) orelse return null));
168 const unaligned_addr = @intFromPtr(unaligned_ptr);168 const unaligned_addr = @intFromPtr(unaligned_ptr);
169 const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), alignment);169 const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), alignment_bytes);
170 const aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);170 const aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);
171 getHeader(aligned_ptr).* = unaligned_ptr;171 getHeader(aligned_ptr).* = unaligned_ptr;
172172
...@@ -195,22 +195,22 @@ const CAllocator = struct {...@@ -195,22 +195,22 @@ const CAllocator = struct {
195 fn alloc(195 fn alloc(
196 _: *anyopaque,196 _: *anyopaque,
197 len: usize,197 len: usize,
198 log2_align: u8,198 alignment: mem.Alignment,
199 return_address: usize,199 return_address: usize,
200 ) ?[*]u8 {200 ) ?[*]u8 {
201 _ = return_address;201 _ = return_address;
202 assert(len > 0);202 assert(len > 0);
203 return alignedAlloc(len, log2_align);203 return alignedAlloc(len, alignment);
204 }204 }
205205
206 fn resize(206 fn resize(
207 _: *anyopaque,207 _: *anyopaque,
208 buf: []u8,208 buf: []u8,
209 log2_buf_align: u8,209 alignment: mem.Alignment,
210 new_len: usize,210 new_len: usize,
211 return_address: usize,211 return_address: usize,
212 ) bool {212 ) bool {
213 _ = log2_buf_align;213 _ = alignment;
214 _ = return_address;214 _ = return_address;
215 if (new_len <= buf.len) {215 if (new_len <= buf.len) {
216 return true;216 return true;
...@@ -227,10 +227,10 @@ const CAllocator = struct {...@@ -227,10 +227,10 @@ const CAllocator = struct {
227 fn free(227 fn free(
228 _: *anyopaque,228 _: *anyopaque,
229 buf: []u8,229 buf: []u8,
230 log2_buf_align: u8,230 alignment: mem.Alignment,
231 return_address: usize,231 return_address: usize,
232 ) void {232 ) void {
233 _ = log2_buf_align;233 _ = alignment;
234 _ = return_address;234 _ = return_address;
235 alignedFree(buf.ptr);235 alignedFree(buf.ptr);
236 }236 }
...@@ -267,28 +267,28 @@ const raw_c_allocator_vtable = Allocator.VTable{...@@ -267,28 +267,28 @@ const raw_c_allocator_vtable = Allocator.VTable{
267fn rawCAlloc(267fn rawCAlloc(
268 _: *anyopaque,268 _: *anyopaque,
269 len: usize,269 len: usize,
270 log2_ptr_align: u8,270 alignment: mem.Alignment,
271 ret_addr: usize,271 ret_addr: usize,
272) ?[*]u8 {272) ?[*]u8 {
273 _ = ret_addr;273 _ = ret_addr;
274 assert(log2_ptr_align <= comptime std.math.log2_int(usize, @alignOf(std.c.max_align_t)));274 assert(alignment.order(.le, comptime .fromByteUnits(@alignOf(std.c.max_align_t))));
275 // Note that this pointer cannot be aligncasted to max_align_t because if275 // Note that this pointer cannot be aligncasted to max_align_t because if
276 // len is < max_align_t then the alignment can be smaller. For example, if276 // len is < max_align_t then the alignment can be smaller. For example, if
277 // max_align_t is 16, but the user requests 8 bytes, there is no built-in277 // max_align_t is 16, but the user requests 8 bytes, there is no built-in
278 // type in C that is size 8 and has 16 byte alignment, so the alignment may278 // type in C that is size 8 and has 16 byte alignment, so the alignment may
279 // be 8 bytes rather than 16. Similarly if only 1 byte is requested, malloc279 // be 8 bytes rather than 16. Similarly if only 1 byte is requested, malloc
280 // is allowed to return a 1-byte aligned pointer.280 // is allowed to return a 1-byte aligned pointer.
281 return @as(?[*]u8, @ptrCast(c.malloc(len)));281 return @ptrCast(c.malloc(len));
282}282}
283283
284fn rawCResize(284fn rawCResize(
285 _: *anyopaque,285 _: *anyopaque,
286 buf: []u8,286 buf: []u8,
287 log2_old_align: u8,287 alignment: mem.Alignment,
288 new_len: usize,288 new_len: usize,
289 ret_addr: usize,289 ret_addr: usize,
290) bool {290) bool {
291 _ = log2_old_align;291 _ = alignment;
292 _ = ret_addr;292 _ = ret_addr;
293293
294 if (new_len <= buf.len)294 if (new_len <= buf.len)
...@@ -305,10 +305,10 @@ fn rawCResize(...@@ -305,10 +305,10 @@ fn rawCResize(
305fn rawCFree(305fn rawCFree(
306 _: *anyopaque,306 _: *anyopaque,
307 buf: []u8,307 buf: []u8,
308 log2_old_align: u8,308 alignment: mem.Alignment,
309 ret_addr: usize,309 ret_addr: usize,
310) void {310) void {
311 _ = log2_old_align;311 _ = alignment;
312 _ = ret_addr;312 _ = ret_addr;
313 c.free(buf.ptr);313 c.free(buf.ptr);
314}314}
...@@ -380,13 +380,13 @@ pub const HeapAllocator = switch (builtin.os.tag) {...@@ -380,13 +380,13 @@ pub const HeapAllocator = switch (builtin.os.tag) {
380 fn alloc(380 fn alloc(
381 ctx: *anyopaque,381 ctx: *anyopaque,
382 n: usize,382 n: usize,
383 log2_ptr_align: u8,383 alignment: mem.Alignment,
384 return_address: usize,384 return_address: usize,
385 ) ?[*]u8 {385 ) ?[*]u8 {
386 _ = return_address;386 _ = return_address;
387 const self: *HeapAllocator = @ptrCast(@alignCast(ctx));387 const self: *HeapAllocator = @ptrCast(@alignCast(ctx));
388388
389 const ptr_align = @as(usize, 1) << @as(Allocator.Log2Align, @intCast(log2_ptr_align));389 const ptr_align = alignment.toByteUnits();
390 const amt = n + ptr_align - 1 + @sizeOf(usize);390 const amt = n + ptr_align - 1 + @sizeOf(usize);
391 const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, .seq_cst);391 const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, .seq_cst);
392 const heap_handle = optional_heap_handle orelse blk: {392 const heap_handle = optional_heap_handle orelse blk: {
...@@ -407,11 +407,11 @@ pub const HeapAllocator = switch (builtin.os.tag) {...@@ -407,11 +407,11 @@ pub const HeapAllocator = switch (builtin.os.tag) {
407 fn resize(407 fn resize(
408 ctx: *anyopaque,408 ctx: *anyopaque,
409 buf: []u8,409 buf: []u8,
410 log2_buf_align: u8,410 alignment: mem.Alignment,
411 new_size: usize,411 new_size: usize,
412 return_address: usize,412 return_address: usize,
413 ) bool {413 ) bool {
414 _ = log2_buf_align;414 _ = alignment;
415 _ = return_address;415 _ = return_address;
416 const self: *HeapAllocator = @ptrCast(@alignCast(ctx));416 const self: *HeapAllocator = @ptrCast(@alignCast(ctx));
417417
...@@ -432,10 +432,10 @@ pub const HeapAllocator = switch (builtin.os.tag) {...@@ -432,10 +432,10 @@ pub const HeapAllocator = switch (builtin.os.tag) {
432 fn free(432 fn free(
433 ctx: *anyopaque,433 ctx: *anyopaque,
434 buf: []u8,434 buf: []u8,
435 log2_buf_align: u8,435 alignment: mem.Alignment,
436 return_address: usize,436 return_address: usize,
437 ) void {437 ) void {
438 _ = log2_buf_align;438 _ = alignment;
439 _ = return_address;439 _ = return_address;
440 const self: *HeapAllocator = @ptrCast(@alignCast(ctx));440 const self: *HeapAllocator = @ptrCast(@alignCast(ctx));
441 windows.HeapFree(self.heap_handle.?, 0, @as(*anyopaque, @ptrFromInt(getRecordPtr(buf).*)));441 windows.HeapFree(self.heap_handle.?, 0, @as(*anyopaque, @ptrFromInt(getRecordPtr(buf).*)));
...@@ -482,6 +482,7 @@ pub fn StackFallbackAllocator(comptime size: usize) type {...@@ -482,6 +482,7 @@ pub fn StackFallbackAllocator(comptime size: usize) type {
482 .vtable = &.{482 .vtable = &.{
483 .alloc = alloc,483 .alloc = alloc,
484 .resize = resize,484 .resize = resize,
485 .remap = remap,
485 .free = free,486 .free = free,
486 },487 },
487 };488 };
...@@ -496,40 +497,55 @@ pub fn StackFallbackAllocator(comptime size: usize) type {...@@ -496,40 +497,55 @@ pub fn StackFallbackAllocator(comptime size: usize) type {
496 fn alloc(497 fn alloc(
497 ctx: *anyopaque,498 ctx: *anyopaque,
498 len: usize,499 len: usize,
499 log2_ptr_align: u8,500 alignment: mem.Alignment,
500 ra: usize,501 ra: usize,
501 ) ?[*]u8 {502 ) ?[*]u8 {
502 const self: *Self = @ptrCast(@alignCast(ctx));503 const self: *Self = @ptrCast(@alignCast(ctx));
503 return FixedBufferAllocator.alloc(&self.fixed_buffer_allocator, len, log2_ptr_align, ra) orelse504 return FixedBufferAllocator.alloc(&self.fixed_buffer_allocator, len, alignment, ra) orelse
504 return self.fallback_allocator.rawAlloc(len, log2_ptr_align, ra);505 return self.fallback_allocator.rawAlloc(len, alignment, ra);
505 }506 }
506507
507 fn resize(508 fn resize(
508 ctx: *anyopaque,509 ctx: *anyopaque,
509 buf: []u8,510 buf: []u8,
510 log2_buf_align: u8,511 alignment: mem.Alignment,
511 new_len: usize,512 new_len: usize,
512 ra: usize,513 ra: usize,
513 ) bool {514 ) bool {
514 const self: *Self = @ptrCast(@alignCast(ctx));515 const self: *Self = @ptrCast(@alignCast(ctx));
515 if (self.fixed_buffer_allocator.ownsPtr(buf.ptr)) {516 if (self.fixed_buffer_allocator.ownsPtr(buf.ptr)) {
516 return FixedBufferAllocator.resize(&self.fixed_buffer_allocator, buf, log2_buf_align, new_len, ra);517 return FixedBufferAllocator.resize(&self.fixed_buffer_allocator, buf, alignment, new_len, ra);
517 } else {518 } else {
518 return self.fallback_allocator.rawResize(buf, log2_buf_align, new_len, ra);519 return self.fallback_allocator.rawResize(buf, alignment, new_len, ra);
520 }
521 }
522
523 fn remap(
524 context: *anyopaque,
525 memory: []u8,
526 alignment: mem.Alignment,
527 new_len: usize,
528 return_address: usize,
529 ) ?[*]u8 {
530 const self: *Self = @ptrCast(@alignCast(context));
531 if (self.fixed_buffer_allocator.ownsPtr(memory.ptr)) {
532 return FixedBufferAllocator.remap(&self.fixed_buffer_allocator, memory, alignment, new_len, return_address);
533 } else {
534 return self.fallback_allocator.rawRemap(memory, alignment, new_len, return_address);
519 }535 }
520 }536 }
521537
522 fn free(538 fn free(
523 ctx: *anyopaque,539 ctx: *anyopaque,
524 buf: []u8,540 buf: []u8,
525 log2_buf_align: u8,541 alignment: mem.Alignment,
526 ra: usize,542 ra: usize,
527 ) void {543 ) void {
528 const self: *Self = @ptrCast(@alignCast(ctx));544 const self: *Self = @ptrCast(@alignCast(ctx));
529 if (self.fixed_buffer_allocator.ownsPtr(buf.ptr)) {545 if (self.fixed_buffer_allocator.ownsPtr(buf.ptr)) {
530 return FixedBufferAllocator.free(&self.fixed_buffer_allocator, buf, log2_buf_align, ra);546 return FixedBufferAllocator.free(&self.fixed_buffer_allocator, buf, alignment, ra);
531 } else {547 } else {
532 return self.fallback_allocator.rawFree(buf, log2_buf_align, ra);548 return self.fallback_allocator.rawFree(buf, alignment, ra);
533 }549 }
534 }550 }
535 };551 };
lib/std/heap/log_to_writer_allocator.zig+33-6
...@@ -23,6 +23,7 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {...@@ -23,6 +23,7 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {
23 .vtable = &.{23 .vtable = &.{
24 .alloc = alloc,24 .alloc = alloc,
25 .resize = resize,25 .resize = resize,
26 .remap = remap,
26 .free = free,27 .free = free,
27 },28 },
28 };29 };
...@@ -31,12 +32,12 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {...@@ -31,12 +32,12 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {
31 fn alloc(32 fn alloc(
32 ctx: *anyopaque,33 ctx: *anyopaque,
33 len: usize,34 len: usize,
34 log2_ptr_align: u8,35 alignment: std.mem.Alignment,
35 ra: usize,36 ra: usize,
36 ) ?[*]u8 {37 ) ?[*]u8 {
37 const self: *Self = @ptrCast(@alignCast(ctx));38 const self: *Self = @ptrCast(@alignCast(ctx));
38 self.writer.print("alloc : {}", .{len}) catch {};39 self.writer.print("alloc : {}", .{len}) catch {};
39 const result = self.parent_allocator.rawAlloc(len, log2_ptr_align, ra);40 const result = self.parent_allocator.rawAlloc(len, alignment, ra);
40 if (result != null) {41 if (result != null) {
41 self.writer.print(" success!\n", .{}) catch {};42 self.writer.print(" success!\n", .{}) catch {};
42 } else {43 } else {
...@@ -48,7 +49,7 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {...@@ -48,7 +49,7 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {
48 fn resize(49 fn resize(
49 ctx: *anyopaque,50 ctx: *anyopaque,
50 buf: []u8,51 buf: []u8,
51 log2_buf_align: u8,52 alignment: std.mem.Alignment,
52 new_len: usize,53 new_len: usize,
53 ra: usize,54 ra: usize,
54 ) bool {55 ) bool {
...@@ -59,7 +60,7 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {...@@ -59,7 +60,7 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {
59 self.writer.print("expand: {} to {}", .{ buf.len, new_len }) catch {};60 self.writer.print("expand: {} to {}", .{ buf.len, new_len }) catch {};
60 }61 }
6162
62 if (self.parent_allocator.rawResize(buf, log2_buf_align, new_len, ra)) {63 if (self.parent_allocator.rawResize(buf, alignment, new_len, ra)) {
63 if (new_len > buf.len) {64 if (new_len > buf.len) {
64 self.writer.print(" success!\n", .{}) catch {};65 self.writer.print(" success!\n", .{}) catch {};
65 }66 }
...@@ -71,15 +72,41 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {...@@ -71,15 +72,41 @@ pub fn LogToWriterAllocator(comptime Writer: type) type {
71 return false;72 return false;
72 }73 }
7374
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
74 fn free(101 fn free(
75 ctx: *anyopaque,102 ctx: *anyopaque,
76 buf: []u8,103 buf: []u8,
77 log2_buf_align: u8,104 alignment: std.mem.Alignment,
78 ra: usize,105 ra: usize,
79 ) void {106 ) void {
80 const self: *Self = @ptrCast(@alignCast(ctx));107 const self: *Self = @ptrCast(@alignCast(ctx));
81 self.writer.print("free : {}\n", .{buf.len}) catch {};108 self.writer.print("free : {}\n", .{buf.len}) catch {};
82 self.parent_allocator.rawFree(buf, log2_buf_align, ra);109 self.parent_allocator.rawFree(buf, alignment, ra);
83 }110 }
84 };111 };
85}112}
lib/std/mem.zig+23-27
...@@ -92,6 +92,7 @@ pub fn ValidationAllocator(comptime T: type) type {...@@ -92,6 +92,7 @@ pub fn ValidationAllocator(comptime T: type) type {
92 .vtable = &.{92 .vtable = &.{
93 .alloc = alloc,93 .alloc = alloc,
94 .resize = resize,94 .resize = resize,
95 .remap = remap,
95 .free = free,96 .free = free,
96 },97 },
97 };98 };
...@@ -105,41 +106,54 @@ pub fn ValidationAllocator(comptime T: type) type {...@@ -105,41 +106,54 @@ pub fn ValidationAllocator(comptime T: type) type {
105 pub fn alloc(106 pub fn alloc(
106 ctx: *anyopaque,107 ctx: *anyopaque,
107 n: usize,108 n: usize,
108 log2_ptr_align: u8,109 alignment: mem.Alignment,
109 ret_addr: usize,110 ret_addr: usize,
110 ) ?[*]u8 {111 ) ?[*]u8 {
111 assert(n > 0);112 assert(n > 0);
112 const self: *Self = @ptrCast(@alignCast(ctx));113 const self: *Self = @ptrCast(@alignCast(ctx));
113 const underlying = self.getUnderlyingAllocatorPtr();114 const underlying = self.getUnderlyingAllocatorPtr();
114 const result = underlying.rawAlloc(n, log2_ptr_align, ret_addr) orelse115 const result = underlying.rawAlloc(n, alignment, ret_addr) orelse
115 return null;116 return null;
116 assert(mem.isAlignedLog2(@intFromPtr(result), log2_ptr_align));117 assert(alignment.check(@intFromPtr(result)));
117 return result;118 return result;
118 }119 }
119120
120 pub fn resize(121 pub fn resize(
121 ctx: *anyopaque,122 ctx: *anyopaque,
122 buf: []u8,123 buf: []u8,
123 log2_buf_align: u8,124 alignment: Alignment,
124 new_len: usize,125 new_len: usize,
125 ret_addr: usize,126 ret_addr: usize,
126 ) bool {127 ) bool {
127 const self: *Self = @ptrCast(@alignCast(ctx));128 const self: *Self = @ptrCast(@alignCast(ctx));
128 assert(buf.len > 0);129 assert(buf.len > 0);
129 const underlying = self.getUnderlyingAllocatorPtr();130 const underlying = self.getUnderlyingAllocatorPtr();
130 return underlying.rawResize(buf, log2_buf_align, new_len, ret_addr);131 return underlying.rawResize(buf, alignment, new_len, ret_addr);
132 }
133
134 pub fn remap(
135 ctx: *anyopaque,
136 buf: []u8,
137 alignment: Alignment,
138 new_len: usize,
139 ret_addr: usize,
140 ) ?[*]u8 {
141 const self: *Self = @ptrCast(@alignCast(ctx));
142 assert(buf.len > 0);
143 const underlying = self.getUnderlyingAllocatorPtr();
144 return underlying.rawRemap(buf, alignment, new_len, ret_addr);
131 }145 }
132146
133 pub fn free(147 pub fn free(
134 ctx: *anyopaque,148 ctx: *anyopaque,
135 buf: []u8,149 buf: []u8,
136 log2_buf_align: u8,150 alignment: Alignment,
137 ret_addr: usize,151 ret_addr: usize,
138 ) void {152 ) void {
139 const self: *Self = @ptrCast(@alignCast(ctx));153 const self: *Self = @ptrCast(@alignCast(ctx));
140 assert(buf.len > 0);154 assert(buf.len > 0);
141 const underlying = self.getUnderlyingAllocatorPtr();155 const underlying = self.getUnderlyingAllocatorPtr();
142 underlying.rawFree(buf, log2_buf_align, ret_addr);156 underlying.rawFree(buf, alignment, ret_addr);
143 }157 }
144158
145 pub fn reset(self: *Self) void {159 pub fn reset(self: *Self) void {
...@@ -167,27 +181,9 @@ pub fn alignAllocLen(full_len: usize, alloc_len: usize, len_align: u29) usize {...@@ -167,27 +181,9 @@ pub fn alignAllocLen(full_len: usize, alloc_len: usize, len_align: u29) usize {
167 return adjusted;181 return adjusted;
168}182}
169183
170const fail_allocator = Allocator{
171 .ptr = undefined,
172 .vtable = &failAllocator_vtable,
173};
174
175const failAllocator_vtable = Allocator.VTable{
176 .alloc = failAllocatorAlloc,
177 .resize = Allocator.noResize,
178 .free = Allocator.noFree,
179};
180
181fn failAllocatorAlloc(_: *anyopaque, n: usize, log2_alignment: u8, ra: usize) ?[*]u8 {
182 _ = n;
183 _ = log2_alignment;
184 _ = ra;
185 return null;
186}
187
188test "Allocator basics" {184test "Allocator basics" {
189 try testing.expectError(error.OutOfMemory, fail_allocator.alloc(u8, 1));185 try testing.expectError(error.OutOfMemory, testing.failing_allocator.alloc(u8, 1));
190 try testing.expectError(error.OutOfMemory, fail_allocator.allocSentinel(u8, 1, 0));186 try testing.expectError(error.OutOfMemory, testing.failing_allocator.allocSentinel(u8, 1, 0));
191}187}
192188
193test "Allocator.resize" {189test "Allocator.resize" {