Compile using blc my-file-name.bl
and run ./out
.
MyAllocator :: struct #base Allocator {
buffer: []u8;
used_bytes: usize;
}
allocator_make :: fn (buffer: []u8) MyAllocator {
return MyAllocator.{
base = Allocator.{ auto &my_allocator_handler },
buffer = buffer,
used_bytes = 0,
};
}
my_allocator_handler :: fn (
allocator: *MyAllocator,
// Operation specify whether we do allocation or free.
operation: AllocOp,
// Pointer to the previously allocated memory.
_: *u8,
// Count of bytes to be allocated.
size: usize,
// Allocation allignment.
alignment: usize,
// Source file where allocator was called.
file: string_view,
// Line in source file where allocator was called.
line: s32) (mem: *u8, err: Error)
{
using AllocOp;
switch operation {
ALLOCATE {
print("Allocate %B called from %:%.", size, file, line);
return allocate(allocator, size, alignment);
}
REALLOCATE {
// To properly support reallocation, we have to store additional metadata
// containing the size of the previous allocated memory associated with input
// ptr pointer.
// This is not implemented in this example to keep things simple.
panic("Rellocation is not supported.");
}
FREE {
print("Free called from %:%.", file, line);
}
RESET, RELEASE {
panic("Unsupported operation: %.", operation);
}
default { panic("Unknown operation."); }
}
return null, OK;
}
allocate :: fn (allocator: *MyAllocator, size: usize, alignment: usize) (mem: *u8, err: Error) {
// Alignment mask.
mask :: ~(alignment - 1);
// We need some additional space to properly align the allocation.
adjusted_size :: size + alignment - 1;
// Calculate total size needed.
needed_size :: allocator.used_bytes + adjusted_size;
// Check if there is space enough in out buffer.
if needed_size > auto allocator.buffer.len {
return null, error("The buffer is full! The buffer size is %B and required size is %B.", allocator.buffer.len, needed_size);
}
// Get free memory pointer.
mem := &allocator.buffer[auto allocator.used_bytes];
// Adjust used size.
allocator.used_bytes += adjusted_size;
// Align memory pointer.
mem = auto ((cast(usize) mem) + alignment - 1 & mask);
return mem, OK;
}
User :: struct {
name: string_view;
age: s32;
}
main :: fn () s32 {
buffer: [2048]u8;
allocator :: allocator_make(buffer);
user :: new(User, true, &allocator);
user.name = "Martin.";
user.age = 32;
print("User = %\n", @user);
free(auto user, &allocator);
return 0;
}