Add `Allocator` record

ada1cb34a3f94680fae1ef659f641dac1a7de19d36d9685a67d4c1f4aa68571d
This will eventually be replaced by a trait.
Alexis Sellier committed ago 1 parent d1aed336
lib/std/lang/alloc.rad +29 -0
121 121
    for i in 0..len * size {
122 122
        newBytes[i] = oldBytes[i];
123 123
    }
124 124
    return new;
125 125
}
126 +
127 +
/// Generic allocator interface.
128 +
///
129 +
/// Bundles an allocation function with an opaque context pointer so that
130 +
/// any allocation strategy (arena, free-list, mmap, pool) can be used
131 +
/// through a uniform interface. The `func` field is called with the context
132 +
/// pointer, a byte size and an alignment, and must return a pointer to
133 +
/// the allocated memory or panic on failure.
134 +
pub record Allocator {
135 +
    /// Allocation function. Returns a pointer to `size` bytes
136 +
    /// aligned to `alignment`, or panics on failure.
137 +
    func: fn(*mut opaque, u32, u32) -> *mut opaque,
138 +
    /// Opaque context pointer passed to `func`.
139 +
    ctx: *mut opaque,
140 +
}
141 +
142 +
/// Create an `Allocator` backed by an `Arena`.
143 +
pub fn arenaAllocator(arena: *mut Arena) -> Allocator {
144 +
    return Allocator {
145 +
        func: arenaAllocFn,
146 +
        ctx: arena as *mut opaque,
147 +
    };
148 +
}
149 +
150 +
/// Arena allocation function conforming to the `Allocator` interface.
151 +
fn arenaAllocFn(ctx: *mut opaque, size: u32, alignment: u32) -> *mut opaque {
152 +
    let arena = ctx as *mut Arena;
153 +
    return try! alloc(arena, size, alignment);
154 +
}
lib/std/lang/alloc/tests.rad +17 -0
101 101
    try super::alloc(&mut arena, 16, 4) catch {
102 102
        failed = true;
103 103
    };
104 104
    try testing::expect(failed);
105 105
}
106 +
107 +
/// Test the Allocator interface backed by an arena.
108 +
@test fn testAllocator() throws (testing::TestError) {
109 +
    static STORAGE: [u8; 256] = undefined;
110 +
    let mut arena = super::new(&mut STORAGE[..]);
111 +
    let a = super::arenaAllocator(&mut arena);
112 +
113 +
    // Allocate through the Allocator indirection.
114 +
    let p1 = a.func(a.ctx, 16, 4);
115 +
    try testing::expect(super::used(&arena) == 16);
116 +
117 +
    let p2 = a.func(a.ctx, 8, 8);
118 +
    try testing::expect(super::used(&arena) == 24);
119 +
120 +
    // Verify the pointers are distinct.
121 +
    try testing::expect(p1 as u64 != p2 as u64);
122 +
}