85 lines
2.8 KiB
C
85 lines
2.8 KiB
C
#include "allocators_internal.h"
|
|
|
|
#define chunks_per_allocation 16
|
|
#define default_chunk_size add_padding(1024)
|
|
#define chunk_alloc(SZ, OCCUPIED) (MemoryChunk){ .data=malloc(SZ), .size=SZ, .occupied_size=OCCUPIED }
|
|
#define curr_chunk (self->chunks+self->curr_chunk_i)
|
|
|
|
__attribute__ ((noinline)) void* ___alloc_realloc_chunk(LinearAllocator* self, size_t size){
|
|
free(curr_chunk->data);
|
|
*curr_chunk=chunk_alloc(size, size);
|
|
return curr_chunk->data;
|
|
}
|
|
|
|
__attribute__ ((noinline)) void* __alloc_new_chunk(LinearAllocator* self, size_t size){
|
|
self->curr_chunk_i++;
|
|
// next chunk has been already allocated
|
|
if(self->curr_chunk_i < self->chunks_count)
|
|
return curr_chunk->data;
|
|
|
|
// self->chunks array is full
|
|
if(self->chunks_count == self->max_chunks_count){
|
|
self->max_chunks_count += chunks_per_allocation;
|
|
self->chunks = realloc(self->chunks, sizeof(MemoryChunk) * self->max_chunks_count);
|
|
}
|
|
|
|
// new chunk allocation
|
|
self->chunks_count++;
|
|
size_t new_chunk_size=default_chunk_size > size ? size : default_chunk_size;
|
|
*curr_chunk=chunk_alloc(new_chunk_size, new_chunk_size);
|
|
return curr_chunk->data;
|
|
}
|
|
|
|
void* LinearAllocator_alloc(allocator_ptr _self, size_t size){
|
|
// assert(_self!=NULL);
|
|
// assert(size>0);
|
|
LinearAllocator* self = (LinearAllocator*)_self;
|
|
size=add_padding(size);
|
|
|
|
// aligned size can fit into the current chunk
|
|
if(curr_chunk->occupied_size + size <= curr_chunk->size){
|
|
void* data_ptr=curr_chunk->data + curr_chunk->occupied_size;
|
|
curr_chunk->occupied_size += size;
|
|
return data_ptr;
|
|
}
|
|
// reallocation of current chunk because it is clean
|
|
if(curr_chunk->occupied_size == 0){
|
|
// It is very unefficient operation.
|
|
// If it happens not only in the first chunk, code have to be refactored
|
|
assert(self->curr_chunk_i==0);
|
|
return ___alloc_realloc_chunk(self, size);
|
|
}
|
|
// creation of a new chunk
|
|
else {
|
|
return __alloc_new_chunk(self, size);
|
|
}
|
|
}
|
|
|
|
void LinearAllocator_free(allocator_ptr _self, void* ptr){
|
|
// LinearAllocator can't free pointers
|
|
}
|
|
|
|
void LinearAllocator_destruct(LinearAllocator* self){
|
|
// assert(_self!=NULL);
|
|
for(u16 chunk_i=0; chunk_i < self->chunks_count; chunk_i++){
|
|
free(self->chunks[chunk_i].data);
|
|
}
|
|
free(self->chunks);
|
|
self->chunks=NULL;
|
|
}
|
|
|
|
void LinearAllocator_construct(LinearAllocator* self, size_t starting_size){
|
|
assert(self!=NULL);
|
|
assert(starting_size>0);
|
|
self->base.alloc_f=LinearAllocator_alloc;
|
|
self->base.free_f=LinearAllocator_free;
|
|
|
|
self->curr_chunk_i=0;
|
|
self->chunks_count=1;
|
|
self->max_chunks_count=chunks_per_allocation;
|
|
self->chunks=malloc(sizeof(*self->chunks) * chunks_per_allocation);
|
|
self->chunks[0]=chunk_alloc(starting_size, 0);
|
|
}
|
|
|
|
kt_define(LinearAllocator, (destruct_t)LinearAllocator_destruct, NULL)
|