Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ jobs:
- uses: actions/checkout@v2
- uses: goto-bus-stop/setup-zig@v2
with:
version: 0.12.0
version: 0.14.0
- run: zig build test
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
zig-cache/
.zig-cache/
3 changes: 2 additions & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.{
.name = "zig-stable-array",
.name = .stable_array,
.version = "0.1.0",
.fingerprint = 0xee760748bd6028de,
.dependencies = .{},
.paths = .{
"build.zig",
Expand Down
35 changes: 18 additions & 17 deletions stable_array.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ const builtin = @import("builtin");
const os = std.os;
const posix = std.posix;
const mem = std.mem;
const heap = std.heap;
const assert = std.debug.assert;

const AllocError = std.mem.Allocator.Error;

const darwin = struct {
extern "c" fn madvise(ptr: [*]align(mem.page_size) u8, length: usize, advice: c_int) c_int;
extern "c" fn madvise(ptr: [*]align(heap.page_size_min) u8, length: usize, advice: c_int) c_int;
};

pub fn StableArray(comptime T: type) type {
Expand All @@ -33,7 +34,7 @@ pub fn StableArrayAligned(comptime T: type, comptime alignment: u29) type {
max_virtual_alloc_bytes: usize,

pub fn init(max_virtual_alloc_bytes: usize) Self {
assert(@mod(max_virtual_alloc_bytes, mem.page_size) == 0); // max_virtual_alloc_bytes must be a multiple of mem.page_size
assert(@mod(max_virtual_alloc_bytes, heap.page_size_min) == 0); // max_virtual_alloc_bytes must be a multiple of heap.page_size_min
return Self{
.items = &[_]T{},
.capacity = 0,
Expand Down Expand Up @@ -208,8 +209,8 @@ pub fn StableArrayAligned(comptime T: type, comptime alignment: u29) type {
} else {
const base_addr: usize = @intFromPtr(self.items.ptr);
const offset_addr: usize = base_addr + new_capacity_bytes;
const addr: [*]align(mem.page_size) u8 = @ptrFromInt(offset_addr);
if (comptime builtin.target.isDarwin()) {
const addr: [*]align(heap.page_size_min) u8 = @ptrFromInt(offset_addr);
if (comptime builtin.os.tag.isDarwin()) {
const MADV_DONTNEED = 4;
const err: c_int = darwin.madvise(addr, bytes_to_free, MADV_DONTNEED);
switch (@as(posix.E, @enumFromInt(err))) {
Expand Down Expand Up @@ -243,7 +244,7 @@ pub fn StableArrayAligned(comptime T: type, comptime alignment: u29) type {
const w = os.windows;
w.VirtualFree(@as(*anyopaque, @ptrCast(self.items.ptr)), 0, w.MEM_RELEASE);
} else {
var slice: []align(mem.page_size) const u8 = undefined;
var slice: []align(heap.page_size_min) const u8 = undefined;
slice.ptr = @alignCast(@as([*]u8, @ptrCast(self.items.ptr)));
slice.len = self.max_virtual_alloc_bytes;
posix.munmap(slice);
Expand Down Expand Up @@ -340,7 +341,7 @@ pub fn StableArrayAligned(comptime T: type, comptime alignment: u29) type {
}

fn calcBytesUsedForCapacity(capacity: usize) usize {
return mem.alignForward(usize, k_sizeof * capacity, mem.page_size);
return mem.alignForward(usize, k_sizeof * capacity, heap.page_size_min);
}
};
}
Expand All @@ -364,15 +365,15 @@ test "init" {
test "append" {
var a = StableArray(u8).init(TEST_VIRTUAL_ALLOC_SIZE);
try a.appendSlice(&[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
assert(a.calcTotalUsedBytes() == mem.page_size);
assert(a.calcTotalUsedBytes() == heap.page_size_min);
for (a.items, 0..) |v, i| {
assert(v == i);
}
a.deinit();

var b = StableArrayAligned(u8, mem.page_size).init(TEST_VIRTUAL_ALLOC_SIZE);
var b = StableArrayAligned(u8, heap.page_size_min).init(TEST_VIRTUAL_ALLOC_SIZE);
try b.appendSlice(&[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
assert(b.calcTotalUsedBytes() == mem.page_size * 10);
assert(b.calcTotalUsedBytes() == heap.page_size_min * 10);
for (b.items, 0..) |v, i| {
assert(v == i);
}
Expand All @@ -384,17 +385,17 @@ test "shrinkAndFree" {
try a.appendSlice(&[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
a.shrinkAndFree(5);

assert(a.calcTotalUsedBytes() == mem.page_size);
assert(a.calcTotalUsedBytes() == heap.page_size_min);
assert(a.items.len == 5);
for (a.items, 0..) |v, i| {
assert(v == i);
}
a.deinit();

var b = StableArrayAligned(u8, mem.page_size).init(TEST_VIRTUAL_ALLOC_SIZE);
var b = StableArrayAligned(u8, heap.page_size_min).init(TEST_VIRTUAL_ALLOC_SIZE);
try b.appendSlice(&[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
b.shrinkAndFree(5);
assert(b.calcTotalUsedBytes() == mem.page_size * 5);
assert(b.calcTotalUsedBytes() == heap.page_size_min * 5);
assert(b.items.len == 5);
for (b.items, 0..) |v, i| {
assert(v == i);
Expand All @@ -404,7 +405,7 @@ test "shrinkAndFree" {
var c = StableArrayAligned(u8, 2048).init(TEST_VIRTUAL_ALLOC_SIZE);
try c.appendSlice(&[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
c.shrinkAndFree(5);
assert(c.calcTotalUsedBytes() == mem.page_size * 3);
assert(c.calcTotalUsedBytes() == heap.page_size_min * 3);
assert(c.capacity == 6);
assert(c.items.len == 5);
for (c.items, 0..) |v, i| {
Expand All @@ -426,10 +427,10 @@ test "resize" {
}

test "out of memory" {
var a = StableArrayAligned(u8, mem.page_size).init(TEST_VIRTUAL_ALLOC_SIZE);
var a = StableArrayAligned(u8, heap.page_size_min).init(TEST_VIRTUAL_ALLOC_SIZE);
defer a.deinit();

const max_capacity: usize = TEST_VIRTUAL_ALLOC_SIZE / mem.page_size;
const max_capacity: usize = TEST_VIRTUAL_ALLOC_SIZE / heap.page_size_min;
try a.appendNTimes(0xFF, max_capacity);
for (a.items) |v| {
assert(v == 0xFF);
Expand Down Expand Up @@ -464,8 +465,8 @@ test "growing retains values" {
var a = StableArray(u8).init(TEST_VIRTUAL_ALLOC_SIZE);
defer a.deinit();

try a.resize(mem.page_size);
try a.resize(heap.page_size_min);
a.items[0] = 0xFF;
try a.resize(mem.page_size * 2);
try a.resize(heap.page_size_min * 2);
assert(a.items[0] == 0xFF);
}
Loading