Add `Allocator` record
ada1cb34a3f94680fae1ef659f641dac1a7de19d36d9685a67d4c1f4aa68571d
This will eventually be replaced by a trait.
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 | + | } |