Change the pool list initializations.feature/data-structs
@@ -6,6 +6,7 @@ bool IZ_ListFindFilterAlwaysTrue(IZ_ListNode* _node, u64 _index) { | |||
void IZ_ListInitialize(IZ_List* list) { | |||
list->root = NULL; | |||
list->length = 0; | |||
} | |||
void IZ_ListTeardown(IZ_List* list) { | |||
@@ -27,6 +28,7 @@ IZ_ListNode* IZ_ListAppendNode(IZ_List* list, void* node_value) { | |||
last_node->next = new_node; | |||
} | |||
new_node->next = NULL; | |||
list->length += 1; | |||
return new_node; | |||
} | |||
@@ -53,6 +55,7 @@ void _IZ_ListDeleteFirstNode(IZ_List* list, IZ_ListFindFilter filter) { | |||
} | |||
SDL_free(iterator); | |||
list->length -= 1; | |||
return; | |||
} while (iterator); | |||
} | |||
@@ -11,6 +11,7 @@ typedef struct IZ_ListNode { | |||
typedef struct { | |||
IZ_ListNode* root; | |||
u64 length; | |||
} IZ_List; | |||
typedef bool IZ_ListFindFilter(IZ_ListNode*, u64); | |||
@@ -71,6 +71,7 @@ spec("data") { | |||
.next = NULL, | |||
}; | |||
list2.root = &existing_node; | |||
list2.length = 1; | |||
} | |||
after_each() { | |||
@@ -86,6 +87,7 @@ spec("data") { | |||
mock_is_called(SDL_malloc), | |||
"Allocator function not called." | |||
); | |||
check(list.length == 1, "Length mismatch."); | |||
} | |||
it("appends new node to non-empty list") { | |||
@@ -98,6 +100,7 @@ spec("data") { | |||
mock_is_called(SDL_malloc), | |||
"Allocator function not called." | |||
); | |||
check(list2.length == 2, "Length mismatch."); | |||
} | |||
} | |||
@@ -160,6 +163,8 @@ spec("data") { | |||
!_IZ_ListFindFirstNode(&list, NodeExists), | |||
"Deleted node still present in list." | |||
); | |||
check(list.length == 2, "Length mismatch."); | |||
} | |||
} | |||
} | |||
@@ -1,7 +1,7 @@ | |||
#include "IZ_pool.h" | |||
void IZ_PoolInitialize(IZ_Pool* pool, size_t size) { | |||
pool->items = &(IZ_List){ .root = NULL }; | |||
IZ_ListInitialize(&pool->items); | |||
pool->memory = SDL_malloc(size); | |||
SDL_memset(pool->memory, 0, size); | |||
pool->allocated_memory = 0; | |||
@@ -9,7 +9,7 @@ void IZ_PoolInitialize(IZ_Pool* pool, size_t size) { | |||
pool->max_size = size; | |||
} | |||
IZ_PoolItem* IZ_PoolAllocate(IZ_Pool* pool, size_t size, u64 priority) { | |||
IZ_PoolItem* IZ_PoolAllocate(IZ_Pool* pool, IZ_PoolAllocationArgs args) { | |||
// 1. check next free allocation for size | |||
// 2. if 1. returns non-null, | |||
@@ -21,20 +21,19 @@ IZ_PoolItem* IZ_PoolAllocate(IZ_Pool* pool, size_t size, u64 priority) { | |||
// } | |||
// } | |||
if (pool->max_size - pool->allocated_memory < size) { | |||
if (pool->max_size - pool->allocated_memory < args.size) { | |||
// TODO deallocate memory based from priority | |||
} | |||
void* pointer = &pool->memory[pool->next_address]; | |||
IZ_ListNode* new_item = IZ_ListAppendNode(pool->items, &(IZ_PoolItem) { | |||
IZ_ListNode* new_item = IZ_ListAppendNode(&pool->items, &(IZ_PoolItem) { | |||
.pointer = pointer, | |||
.size = size, | |||
.priority = priority, | |||
.args = args, | |||
.pool = pool, | |||
}); | |||
pool->next_address = (pool->next_address + size) % POOL_MAX_SIZE; | |||
pool->allocated_memory += size; | |||
pool->next_address = (pool->next_address + args.size) % POOL_MAX_SIZE; | |||
pool->allocated_memory += args.size; | |||
return new_item->value; | |||
} | |||
@@ -43,7 +42,7 @@ IZ_LIST_FILTER_FUNCTION(__current_item) bool IZ_PoolGetSameItem(IZ_ListNode* nod | |||
} | |||
void IZ_PoolDeallocate(IZ_PoolItem* item) { | |||
IZ_ListDeleteFirstNode(__current_item, item)(item->pool->items, IZ_PoolGetSameItem); | |||
IZ_ListDeleteFirstNode(__current_item, item)(&item->pool->items, IZ_PoolGetSameItem); | |||
} | |||
void IZ_PoolTeardown(IZ_Pool* pool) { | |||
@@ -10,14 +10,19 @@ | |||
struct IZ_Pool; | |||
typedef struct { | |||
void* pointer; | |||
size_t size; | |||
u64 priority; | |||
u64 timestamp; | |||
} IZ_PoolAllocationArgs; | |||
typedef struct { | |||
void* pointer; | |||
IZ_PoolAllocationArgs args; | |||
struct IZ_Pool* pool; | |||
} IZ_PoolItem; | |||
typedef struct IZ_Pool { | |||
IZ_List* items; | |||
IZ_List items; | |||
u64 next_address; | |||
u64 allocated_memory; | |||
size_t max_size; | |||
@@ -26,7 +31,7 @@ typedef struct IZ_Pool { | |||
void IZ_PoolInitialize(IZ_Pool*, size_t); | |||
IZ_PoolItem* IZ_PoolAllocate(IZ_Pool*, size_t, u64); | |||
IZ_PoolItem* IZ_PoolAllocate(IZ_Pool*, IZ_PoolAllocationArgs); | |||
void IZ_PoolDeallocate(IZ_PoolItem*); | |||
@@ -17,7 +17,7 @@ struct DummyStruct { | |||
spec("memory") { | |||
describe("pool") { | |||
describe("PoolInitialize") { | |||
describe("Initialize") { | |||
static IZ_Pool pool; | |||
after_each() { | |||
@@ -53,7 +53,7 @@ spec("memory") { | |||
} | |||
} | |||
describe("PoolAllocate") { | |||
describe("Allocate") { | |||
static IZ_Pool pool; | |||
after_each() { | |||
@@ -63,8 +63,17 @@ spec("memory") { | |||
it("assigns contiguous memory") { | |||
IZ_PoolInitialize(&pool, POOL_MAX_SIZE); | |||
void* p1 = IZ_PoolAllocate(&pool, sizeof(struct DummyStruct), 0)->pointer; | |||
void* p2 = IZ_PoolAllocate(&pool, sizeof(u8), 0)->pointer; | |||
// FIXME: access violation error | |||
void* p1 = IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(struct DummyStruct), | |||
.priority = 0, | |||
.timestamp = 0, | |||
})->pointer; | |||
void* p2 = IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(u8), | |||
.priority = 0, | |||
.timestamp = 0, | |||
})->pointer; | |||
check( | |||
p2 - p1 == sizeof(struct DummyStruct), | |||
@@ -75,9 +84,21 @@ spec("memory") { | |||
it("ignores previously deallocated items") { | |||
IZ_PoolInitialize(&pool, POOL_MAX_SIZE); | |||
void* p1 = IZ_PoolAllocate(&pool, sizeof(struct DummyStruct), 0)->pointer; | |||
void* p2 = IZ_PoolAllocate(&pool, sizeof(u8), 0)->pointer; | |||
void* p3 = IZ_PoolAllocate(&pool, sizeof(u8), 0)->pointer; | |||
void* p1 = IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(struct DummyStruct), | |||
.priority = 0, | |||
.timestamp = 0, | |||
})->pointer; | |||
void* p2 = IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(u8), | |||
.priority = 0, | |||
.timestamp = 0, | |||
})->pointer; | |||
void* p3 = IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(u8), | |||
.priority = 0, | |||
.timestamp = 0, | |||
})->pointer; | |||
IZ_PoolDeallocate(p2); | |||
@@ -90,16 +111,32 @@ spec("memory") { | |||
it("deallocates old items to make way for new ones when the memory is full") { | |||
IZ_PoolInitialize(&pool, sizeof(u32)); | |||
IZ_PoolAllocate(&pool, sizeof(u16), 1); | |||
IZ_PoolAllocate(&pool, sizeof(u8), 0); | |||
IZ_PoolAllocate(&pool, sizeof(u8), 0); | |||
IZ_PoolAllocate(&pool, sizeof(u8), 0); | |||
IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(u16), | |||
.priority = 0, | |||
.timestamp = 0, | |||
}); | |||
IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(u8), | |||
.priority = 0, | |||
.timestamp = 0, | |||
}); | |||
IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(u8), | |||
.priority = 0, | |||
.timestamp = 0, | |||
}); | |||
IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||
.size = sizeof(u8), | |||
.priority = 0, | |||
.timestamp = 0, | |||
}); | |||
} | |||
} | |||
describe("PoolDeallocate") {} | |||
describe("Deallocate") {} | |||
describe("PoolTeardown") { | |||
describe("Teardown") { | |||
static IZ_Pool pool; | |||
before_each() { | |||