lib/deadalloc/src/class.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 pub const min_alignment: usize = 16;
4 pub const page_size: usize = 4096;
5 pub const max_small_size: usize = 1024 * 1024;
6
7 pub const sizes = [_]usize{
8 16,
9 32,
10 64,
11 128,
12 256,
13 512,
14 1024,
15 2048,
16 4096,
17 8192,
18 16384,
19 32768,
20 65536,
21 131072,
22 262144,
23 524288,
24 1048576,
25 };
26
27 pub const count = sizes.len;
28
29 pub fn indexFor(len: usize, alignment: std.mem.Alignment) ?usize {
30 const requested_len = @max(len, min_alignment);
31 if (requested_len > max_small_size) return null;
32
33 const requested_alignment = @max(alignment.toByteUnits(), min_alignment);
34 for (sizes, 0..) |class_size, index| {
35 if (class_size >= requested_len and class_size >= requested_alignment) return index;
36 }
37 return null;
38 }
39
40 pub fn size(index: usize) usize {
41 return sizes[index];
42 }
43
44 pub fn nextPowerOfTwo(value: usize) ?usize {
45 if (value == 0) return 1;
46 if (value > (std.math.maxInt(usize) >> 1) + 1) return null;
47 return std.math.ceilPowerOfTwo(usize, value) catch null;
48 }
49
50 test "classes are powers of two and cover the small range" {
51 var previous: usize = 0;
52 for (sizes) |class_size| {
53 try std.testing.expect(class_size > previous);
54 try std.testing.expect(std.math.isPowerOfTwo(class_size));
55 previous = class_size;
56 }
57 try std.testing.expectEqual(max_small_size, sizes[sizes.len - 1]);
58 }
59
60 test "lookup respects requested size and alignment" {
61 inline for (.{ 1, 8, 16, 32, 4096, 65536 }) |alignment| {
62 var len: usize = 1;
63 while (len <= max_small_size) : (len *= 2) {
64 const index = indexFor(len, .fromByteUnits(alignment)) orelse return error.MissingClass;
65 const class_size = size(index);
66 try std.testing.expect(class_size >= len);
67 try std.testing.expect(class_size >= @max(alignment, min_alignment));
68 }
69 }
70 }