mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
107 lines
3.2 KiB
C
107 lines
3.2 KiB
C
module std::mem;
|
|
|
|
const TEMP_BLOCK_SIZE = 1024;
|
|
const TEMP_PAGES = 64;
|
|
|
|
private char[TEMP_BLOCK_SIZE * TEMP_PAGES] allocator_static_storage;
|
|
private void*[TEMP_PAGES] allocator_static_page_storage;
|
|
|
|
SlotAllocator default_allocator = {
|
|
.pages = &allocator_static_storage,
|
|
.page_size = TEMP_BLOCK_SIZE,
|
|
.page_count = TEMP_PAGES,
|
|
.bitmask = TEMP_PAGES - 1,
|
|
.current_page = 0,
|
|
};
|
|
|
|
struct SlotAllocator
|
|
{
|
|
void* pages;
|
|
usize page_size;
|
|
usize page_count;
|
|
usize bitmask;
|
|
usize current_page;
|
|
}
|
|
|
|
fn void*! SlotAllocator.alloc(SlotAllocator *allocator, usize size)
|
|
{
|
|
void* active_page = (char*)(allocator.pages) + allocator.current_page * allocator.page_size;
|
|
void** page_pointer = (void**)(active_page);
|
|
if (*page_pointer)
|
|
{
|
|
// TODO fix
|
|
main_allocator.free(*page_pointer)?;
|
|
*page_pointer = null;
|
|
}
|
|
if (size > allocator.page_size - $sizeof(page_pointer))
|
|
{
|
|
void* mem = main_allocator.alloc(size)?;
|
|
*page_pointer = mem;
|
|
allocator.current_page = (allocator.current_page + 1) & (allocator.bitmask);
|
|
return mem;
|
|
}
|
|
allocator.current_page = (allocator.current_page + 1) & (allocator.bitmask);
|
|
return &page_pointer[1];
|
|
}
|
|
|
|
|
|
struct RingAllocator
|
|
{
|
|
char *data;
|
|
usize size;
|
|
usize offset;
|
|
}
|
|
|
|
|
|
fn void* RingAllocator.alloc(RingAllocator *allocator, usize size)
|
|
{
|
|
if (size > allocator.size) return null;
|
|
// Wraparound? If so, start at the beginning.
|
|
if (allocator.offset + size > allocator.size)
|
|
{
|
|
allocator.offset = size;
|
|
return allocator.data;
|
|
}
|
|
void* data = allocator.offset + allocator.data;
|
|
allocator.offset = (allocator.offset + size) & allocator.size;
|
|
return data;
|
|
}
|
|
|
|
fn void* RingAllocator.realloc(RingAllocator *allocator, void* ptr, usize size)
|
|
{
|
|
if (size > allocator.size) return null;
|
|
assert(allocator.data >= ptr && ptr < allocator.data + size, "Realloc on other allocator.");
|
|
// 1. The pointer is before the allocator
|
|
if (allocator.data + allocator.offset > ptr)
|
|
{
|
|
if (allocator.data + allocator.size < ptr + size)
|
|
{
|
|
// 1a. There is not enough space, we need to copy to the start.
|
|
usize pointer_offset = ptr - allocator.data;
|
|
usize copy_len = pointer_offset + size > allocator.offset ? allocator.offset - pointer_offset : size;
|
|
//memcpy(allocator.data, ptr, copy_len);
|
|
allocator.offset = size;
|
|
return allocator.data;
|
|
}
|
|
// 1b. There is enough space, so we just change the offset:
|
|
allocator.offset = ptr - allocator.data + size;
|
|
return ptr;
|
|
}
|
|
// 2. The pointer is after the allocator
|
|
// 2a. Is there sufficient space?
|
|
if (ptr + size <= allocator.data + allocator.size)
|
|
{
|
|
// Good, if so we simply change the offset and return the pointer.
|
|
allocator.offset = ptr - allocator.data + size;
|
|
return ptr;
|
|
}
|
|
// 2b. Not sufficient space, we copy to the beginning.
|
|
usize pointer_offset = ptr - allocator.data;
|
|
usize copy_len = allocator.size - (ptr - allocator.data);
|
|
if (copy_len > size) copy_len = size;
|
|
//memcpy(allocator.data, ptr, copy_len);
|
|
allocator.offset = size;
|
|
return allocator.data;
|
|
}
|
|
|