Skip to content

Instantly share code, notes, and snippets.

@pervognsen pervognsen/allocators.ion
Last active Jul 12, 2019

Embed
What would you like to do?
func noop_free(data: void*, ptr: void*) {
}
struct TempAllocator {
base: Allocator;
start: void*;
next: void*;
end: void*;
}
struct TempMark {
ptr: void*;
}
func temp_alloc(allocator: void*, size: usize, align: usize): void* {
self: TempAllocator* = allocator;
aligned := (uintptr(self.next) + align - 1) & ~(align - 1);
next := aligned + size;
if (next > uintptr(self.end)) {
return 0;
}
self.next = (:void*)next;
return (:void*)aligned;
}
func temp_allocator(buf: void*, size: usize): TempAllocator {
return {{temp_alloc, noop_free}, buf, buf, buf + size};
}
func temp_begin(self: TempAllocator*): TempMark {
return {self.next};
}
func temp_end(self: TempAllocator*, mark: TempMark) {
ptr := mark.ptr;
#assert(self.start <= ptr && ptr <= self.end);
self.next = ptr;
}
struct ArenaAllocator {
base: Allocator;
allocator: Allocator*;
block_size: usize;
blocks: char*[];
next: char*;
end: char*;
}
const ARENA_MIN_BLOCK_SIZE: usize = sizeof(ullong); // small just to test things, would normally be 1 MB or whatever
const ARENA_MIN_BLOCK_ALIGN: usize = sizeof(ullong);
func arena_allocator(allocator: void*): ArenaAllocator {
return {{arena_alloc, noop_free}, allocator, ARENA_MIN_BLOCK_SIZE};
}
func arena_alloc_grow(self: ArenaAllocator*, size: usize, align: usize): void* {
block_size := 2*self.block_size;
if (block_size < size) {
block_size = size;
}
block_align := ARENA_MIN_BLOCK_ALIGN;
if (block_align < align) {
block_align = align;
}
block: char* = generic_alloc(self.allocator, block_size, block_align);
if (!block) {
return 0;
}
apush(self.blocks, block);
self.block_size = block_size;
self.next = block + size;
self.end = block + block_size;
return block;
}
func arena_alloc(allocator: void*, size: usize, align: usize): void* {
self: ArenaAllocator* = allocator;
aligned := (uintptr(self.next) + align - 1) & ~(align - 1);
next := aligned + size;
if (next > uintptr(self.end)) {
return arena_alloc_grow(self, size, align);
}
self.next = (:char*)next;
return (:void*)aligned;
}
func arena_free(self: ArenaAllocator*) {
for (i := 0; i < alen(self.blocks); i++) {
generic_free(self.allocator, self.blocks[i]);
}
afree(self.blocks);
}
enum AllocatorEventKind {
EVENT_ALLOC,
EVENT_FREE,
}
struct AllocatorEvent {
kind: AllocatorEventKind;
time: time_t;
ptr: void*;
size: usize;
align: usize;
}
struct LoggingAllocator {
base: Allocator;
allocator: Allocator*;
events: AllocatorEvent[];
}
func logging_alloc(allocator: void*, size: usize, align: usize): void* {
self: LoggingAllocator* = allocator;
ptr := generic_alloc(self.allocator, size, align);
apush(self.events, {EVENT_ALLOC, time(0), ptr, size, align});
return ptr;
}
func logging_free(allocator: void*, ptr: void*) {
self: LoggingAllocator* = allocator;
generic_free(self.allocator, ptr);
apush(self.events, {EVENT_FREE, time(0), ptr});
}
func logging_allocator(allocator: Allocator*): LoggingAllocator {
return {{logging_alloc, logging_free}, allocator};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.