Skip to content

Commit a9a2831

Browse files
committed
new allocator interface
1 parent 129a4fb commit a9a2831

File tree

11 files changed

+642
-462
lines changed

11 files changed

+642
-462
lines changed

lib/std/array_list.zig

+4-2
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
219219
if (better_capacity >= new_capacity) break;
220220
}
221221

222-
const new_memory = try self.allocator.realloc(self.allocatedSlice(), better_capacity);
222+
const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
223+
assert(new_memory.len >= better_capacity);
223224
self.items.ptr = new_memory.ptr;
224225
self.capacity = new_memory.len;
225226
}
@@ -441,7 +442,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
441442
if (better_capacity >= new_capacity) break;
442443
}
443444

444-
const new_memory = try allocator.realloc(self.allocatedSlice(), better_capacity);
445+
const new_memory = try allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
446+
assert(new_memory.len >= better_capacity);
445447
self.items.ptr = new_memory.ptr;
446448
self.capacity = new_memory.len;
447449
}

lib/std/c.zig

+11
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,17 @@ pub extern "c" fn setuid(uid: c_uint) c_int;
232232

233233
pub extern "c" fn aligned_alloc(alignment: usize, size: usize) ?*c_void;
234234
pub extern "c" fn malloc(usize) ?*c_void;
235+
236+
pub usingnamespace switch (builtin.os.tag) {
237+
.linux, .freebsd, .kfreebsd, .netbsd, .openbsd => struct {
238+
pub extern "c" fn malloc_usable_size(?*const c_void) usize;
239+
},
240+
.macosx, .ios, .watchos, .tvos => struct {
241+
pub extern "c" fn malloc_size(?*const c_void) usize;
242+
},
243+
else => struct {},
244+
};
245+
235246
pub extern "c" fn realloc(?*c_void, usize) ?*c_void;
236247
pub extern "c" fn free(*c_void) void;
237248
pub extern "c" fn posix_memalign(memptr: **c_void, alignment: usize, size: usize) c_int;

lib/std/heap.zig

+291-326
Large diffs are not rendered by default.

lib/std/heap/arena_allocator.zig

+7-22
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ pub const ArenaAllocator = struct {
2020
pub fn promote(self: State, child_allocator: *Allocator) ArenaAllocator {
2121
return .{
2222
.allocator = Allocator{
23-
.reallocFn = realloc,
24-
.shrinkFn = shrink,
23+
.allocFn = alloc,
24+
.resizeFn = Allocator.noResize,
2525
},
2626
.child_allocator = child_allocator,
2727
.state = self,
@@ -61,38 +61,23 @@ pub const ArenaAllocator = struct {
6161
return buf_node;
6262
}
6363

64-
fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
64+
fn alloc(allocator: *Allocator, n: usize, ptr_align: u29, len_align: u29) ![]u8 {
6565
const self = @fieldParentPtr(ArenaAllocator, "allocator", allocator);
6666

67-
var cur_node = if (self.state.buffer_list.first) |first_node| first_node else try self.createNode(0, n + alignment);
67+
var cur_node = if (self.state.buffer_list.first) |first_node| first_node else try self.createNode(0, n + ptr_align);
6868
while (true) {
6969
const cur_buf = cur_node.data[@sizeOf(BufNode)..];
7070
const addr = @ptrToInt(cur_buf.ptr) + self.state.end_index;
71-
const adjusted_addr = mem.alignForward(addr, alignment);
71+
const adjusted_addr = mem.alignForward(addr, ptr_align);
7272
const adjusted_index = self.state.end_index + (adjusted_addr - addr);
7373
const new_end_index = adjusted_index + n;
7474
if (new_end_index > cur_buf.len) {
75-
cur_node = try self.createNode(cur_buf.len, n + alignment);
75+
cur_node = try self.createNode(cur_buf.len, n + ptr_align);
7676
continue;
7777
}
7878
const result = cur_buf[adjusted_index..new_end_index];
7979
self.state.end_index = new_end_index;
80-
return result;
80+
return result[0..mem.alignAllocLen(result.len, n, len_align)];
8181
}
8282
}
83-
84-
fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
85-
if (new_size <= old_mem.len and new_align <= new_size) {
86-
// We can't do anything with the memory, so tell the client to keep it.
87-
return error.OutOfMemory;
88-
} else {
89-
const result = try alloc(allocator, new_size, new_align);
90-
@memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
91-
return result;
92-
}
93-
}
94-
95-
fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
96-
return old_mem[0..new_size];
97-
}
9883
};

lib/std/heap/logging_allocator.zig

+37-24
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,45 @@ pub fn LoggingAllocator(comptime OutStreamType: type) type {
1515
pub fn init(parent_allocator: *Allocator, out_stream: OutStreamType) Self {
1616
return Self{
1717
.allocator = Allocator{
18-
.reallocFn = realloc,
19-
.shrinkFn = shrink,
18+
.allocFn = alloc,
19+
.resizeFn = resize,
2020
},
2121
.parent_allocator = parent_allocator,
2222
.out_stream = out_stream,
2323
};
2424
}
2525

26-
fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
26+
fn alloc(allocator: *Allocator, len: usize, ptr_align: u29, len_align: u29) error{OutOfMemory}![]u8 {
2727
const self = @fieldParentPtr(Self, "allocator", allocator);
28-
if (old_mem.len == 0) {
29-
self.out_stream.print("allocation of {} ", .{new_size}) catch {};
30-
} else {
31-
self.out_stream.print("resize from {} to {} ", .{ old_mem.len, new_size }) catch {};
32-
}
33-
const result = self.parent_allocator.reallocFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
28+
self.out_stream.print("alloc : {}", .{len}) catch {};
29+
const result = self.parent_allocator.callAllocFn(len, ptr_align, len_align);
3430
if (result) |buff| {
35-
self.out_stream.print("success!\n", .{}) catch {};
31+
self.out_stream.print(" success!\n", .{}) catch {};
3632
} else |err| {
37-
self.out_stream.print("failure!\n", .{}) catch {};
33+
self.out_stream.print(" failure!\n", .{}) catch {};
3834
}
3935
return result;
4036
}
4137

42-
fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
38+
fn resize(allocator: *Allocator, buf: []u8, new_len: usize, len_align: u29) error{OutOfMemory}!usize {
4339
const self = @fieldParentPtr(Self, "allocator", allocator);
44-
const result = self.parent_allocator.shrinkFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
45-
if (new_size == 0) {
46-
self.out_stream.print("free of {} bytes success!\n", .{old_mem.len}) catch {};
40+
if (new_len == 0) {
41+
self.out_stream.print("free : {}\n", .{buf.len}) catch {};
42+
} else if (new_len <= buf.len) {
43+
self.out_stream.print("shrink: {} to {}\n", .{buf.len, new_len}) catch {};
4744
} else {
48-
self.out_stream.print("shrink from {} bytes to {} bytes success!\n", .{ old_mem.len, new_size }) catch {};
45+
self.out_stream.print("expand: {} to {}", .{ buf.len, new_len }) catch {};
46+
}
47+
if (self.parent_allocator.callResizeFn(buf, new_len, len_align)) |resized_len| {
48+
if (new_len > buf.len) {
49+
self.out_stream.print(" success!\n", .{}) catch {};
50+
}
51+
return resized_len;
52+
} else |e| {
53+
std.debug.assert(new_len > buf.len);
54+
self.out_stream.print(" failure!\n", .{}) catch {};
55+
return e;
4956
}
50-
return result;
5157
}
5258
};
5359
}
@@ -60,17 +66,24 @@ pub fn loggingAllocator(
6066
}
6167

6268
test "LoggingAllocator" {
63-
var buf: [255]u8 = undefined;
64-
var fbs = std.io.fixedBufferStream(&buf);
69+
var log_buf: [255]u8 = undefined;
70+
var fbs = std.io.fixedBufferStream(&log_buf);
6571

66-
const allocator = &loggingAllocator(std.testing.allocator, fbs.outStream()).allocator;
72+
var allocator_buf: [10]u8 = undefined;
73+
var fixedBufferAllocator = std.mem.sanityWrap(std.heap.FixedBufferAllocator.init(&allocator_buf));
74+
const allocator = &loggingAllocator(&fixedBufferAllocator.allocator, fbs.outStream()).allocator;
6775

68-
const ptr = try allocator.alloc(u8, 10);
69-
allocator.free(ptr);
76+
var a = try allocator.alloc(u8, 10);
77+
a.len = allocator.shrinkBytes(a, 5, 0);
78+
std.debug.assert(a.len == 5);
79+
std.testing.expectError(error.OutOfMemory, allocator.callResizeFn(a, 20, 0));
80+
allocator.free(a);
7081

7182
std.testing.expectEqualSlices(u8,
72-
\\allocation of 10 success!
73-
\\free of 10 bytes success!
83+
\\alloc : 10 success!
84+
\\shrink: 10 to 5
85+
\\expand: 5 to 20 failure!
86+
\\free : 5
7487
\\
7588
, fbs.getWritten());
7689
}

0 commit comments

Comments
 (0)