Compare commits
2 Commits
bcebc14b5a
...
f10b74763e
Author | SHA1 | Date | |
---|---|---|---|
rhuibertsjr | f10b74763e | ||
rhuibertsjr | 3866404505 |
|
@ -1,7 +0,0 @@
|
||||||
12-04-2024 René Huiberts <rhuibertsjr@gmail.com>
|
|
||||||
|
|
||||||
Updated: references & documentation
|
|
||||||
|
|
||||||
12-04-2024 René Huiberts <rhuibertsjr@gmail.com>
|
|
||||||
|
|
||||||
Added: project layout
|
|
81
src/arena.c
81
src/arena.c
|
@ -1,40 +1,93 @@
|
||||||
|
|
||||||
internal Arena *
|
internal Arena *
|
||||||
arena_initialize(u64 size)
|
arena_initialize(u64 size, b8 growable)
|
||||||
{
|
{
|
||||||
Arena *result = 0;
|
Arena *result = 0;
|
||||||
|
void *backing_buffer = platform_memory_reserve(size);
|
||||||
void *backing_buffer = malloc(size);
|
|
||||||
|
|
||||||
if (backing_buffer != NULL)
|
if (backing_buffer != NULL)
|
||||||
{
|
{
|
||||||
result = (Arena*) backing_buffer;
|
platform_memory_commit(backing_buffer, ARENA_INITIAL_COMMIT_SIZE);
|
||||||
|
|
||||||
result->buffer = backing_buffer;
|
result = (Arena*) backing_buffer;
|
||||||
result->offset = sizeof(Arena);
|
result->backing_buffer = (u64*) backing_buffer;
|
||||||
result->size = sizeof(Arena) + size;
|
result->current = result;
|
||||||
|
result->prev = 0;
|
||||||
|
|
||||||
|
// rhjr: immutable arena header
|
||||||
|
result->base_pos =
|
||||||
|
memory_align(sizeof(Arena), ARENA_DEFAULT_ALIGNMENT);
|
||||||
|
result->offset = result->base_pos;
|
||||||
|
|
||||||
|
result->growable = growable;
|
||||||
|
result->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rhjr: arenas should be instantiated early on in the programs lifetime, that
|
||||||
|
// is why this assertion will also be used in production.
|
||||||
|
ASSERT(result != 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Arena *
|
||||||
|
arena_initialize_default()
|
||||||
|
{
|
||||||
|
Arena *result = arena_initialize(ARENA_DEFAULT_RESERVE_SIZE, 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void *
|
internal void *
|
||||||
arena_allocate(Arena *arena, u64 size)
|
arena_allocate(Arena *arena, u64 size)
|
||||||
{
|
{
|
||||||
void *result = 0;
|
Arena *current = arena->current;
|
||||||
|
u64 pos_cur = current->base_pos + current->offset;
|
||||||
|
u64 pos_mem = memory_align(pos_cur, ARENA_DEFAULT_ALIGNMENT);
|
||||||
|
u64 pos_new = pos_mem + size;
|
||||||
|
|
||||||
if (arena->offset + size <= arena->size)
|
if (current->size < pos_new && current->growable)
|
||||||
{
|
{
|
||||||
result = (void*)((u64) arena->buffer + (u64) arena->offset);
|
Arena *new_memory_bock;
|
||||||
arena->offset += size;
|
|
||||||
|
if (size > ARENA_DEFAULT_RESERVE_SIZE)
|
||||||
|
{
|
||||||
|
// rhjr: TODO add support for allocations larger then a single page, in a
|
||||||
|
// single allocation call.
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_memory_bock = arena_initialize_default();
|
||||||
|
|
||||||
|
if (new_memory_bock)
|
||||||
|
{
|
||||||
|
stack_push(arena->current, new_memory_bock, prev);
|
||||||
|
|
||||||
|
current = new_memory_bock;
|
||||||
|
|
||||||
|
pos_mem =
|
||||||
|
memory_align(current->offset, ARENA_DEFAULT_ALIGNMENT);
|
||||||
|
pos_new = current->offset + size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
memset(result, 0, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
void *memory = (void*)((u64) current->backing_buffer + pos_mem);
|
||||||
|
arena->offset = pos_new;
|
||||||
|
|
||||||
|
platform_memory_commit(memory, size);
|
||||||
|
memset(memory, 0, size);
|
||||||
|
|
||||||
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
arena_release(Arena *arena)
|
arena_release(Arena *arena)
|
||||||
{
|
{
|
||||||
arena->offset = 0;
|
for (Arena *node = arena->current, *prev = 0; node != 0; node = prev)
|
||||||
|
{
|
||||||
|
prev = node->prev;
|
||||||
|
platform_memory_release(node, node->size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/arena.h
25
src/arena.h
|
@ -1,19 +1,30 @@
|
||||||
#ifndef ARENA_H
|
#ifndef ARENA_H
|
||||||
#define ARENA_H
|
#define ARENA_H
|
||||||
|
|
||||||
|
#define ARENA_INITIAL_COMMIT_SIZE sizeof(struct Arena)
|
||||||
|
#define ARENA_DEFAULT_ALIGNMENT 0
|
||||||
|
|
||||||
|
#ifndef ARENA_DEFAULT_RESERVE_SIZE
|
||||||
|
# define ARENA_DEFAULT_RESERVE_SIZE KB(4)
|
||||||
|
#endif // ARENA_DEFAULT_RESERVE_SIZE
|
||||||
|
|
||||||
typedef struct Arena Arena;
|
typedef struct Arena Arena;
|
||||||
struct Arena {
|
struct Arena {
|
||||||
u64 *buffer;
|
struct Arena *current;
|
||||||
|
struct Arena *prev;
|
||||||
|
u64 *backing_buffer;
|
||||||
|
u64 base_pos;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
b8 growable;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal Arena * arena_initialize(u64 size);
|
//= rhjr: arenas
|
||||||
|
|
||||||
internal void * arena_allocate(Arena *arena, u64 size);
|
internal Arena * arena_initialize(u64 size, b8 growable);
|
||||||
internal void arena_release(Arena *arena);
|
internal Arena * arena_initialize_default();
|
||||||
|
|
||||||
//= rhjr: arena helpers
|
internal void * arena_allocate(Arena *arena, u64 size);
|
||||||
|
|
||||||
#define arena_push_array(arena, type, count) \
|
#define arena_push_array(arena, type, count) \
|
||||||
(type*) arena_allocate((arena), sizeof(type) * (count))
|
(type*) arena_allocate((arena), sizeof(type) * (count))
|
||||||
|
@ -21,8 +32,12 @@ internal void arena_release(Arena *arena);
|
||||||
#define arena_push(arena, type) \
|
#define arena_push(arena, type) \
|
||||||
(type*) arena_allocate((arena), sizeof(type))
|
(type*) arena_allocate((arena), sizeof(type))
|
||||||
|
|
||||||
|
internal void arena_release(Arena *arena);
|
||||||
|
|
||||||
//= rhjr: memory helpers
|
//= rhjr: memory helpers
|
||||||
|
|
||||||
|
#define memory_align(x, b) ((b != 0) ? (((x) + (b) - 1) & (~(b - 1))) : (x))
|
||||||
|
|
||||||
#define memory_zero(s,z) memset((s), 0, (z))
|
#define memory_zero(s,z) memset((s), 0, (z))
|
||||||
#define memory_zero_struct(s) memory_zero((s), sizeof(*(s)))
|
#define memory_zero_struct(s) memory_zero((s), sizeof(*(s)))
|
||||||
|
|
||||||
|
|
18
src/base.h
18
src/base.h
|
@ -18,12 +18,30 @@ typedef int16_t i16;
|
||||||
typedef int32_t i32;
|
typedef int32_t i32;
|
||||||
typedef int64_t i64;
|
typedef int64_t i64;
|
||||||
|
|
||||||
|
typedef uint8_t b8;
|
||||||
|
typedef uint16_t b16;
|
||||||
|
typedef uint32_t b32;
|
||||||
|
typedef uint64_t b64;
|
||||||
|
|
||||||
#define KB(b) ((b) << 10)
|
#define KB(b) ((b) << 10)
|
||||||
#define MB(b) ((b) << 20)
|
#define MB(b) ((b) << 20)
|
||||||
|
|
||||||
#define STATEMENT(S) do{ S } while(0)
|
#define STATEMENT(S) do{ S } while(0)
|
||||||
#define ASSERT(c) STATEMENT( if (!(c)){ (*(volatile int*)0 = 0); } )
|
#define ASSERT(c) STATEMENT( if (!(c)){ (*(volatile int*)0 = 0); } )
|
||||||
|
#define STATIC_ASSERT(c,l) typedef u8 Glue(l,__LINE__) [(c)?1:-1]
|
||||||
|
|
||||||
#define MIN(A,B) (((A)<(B))?(A):(B))
|
#define MIN(A,B) (((A)<(B))?(A):(B))
|
||||||
|
|
||||||
|
//= rhjr: linked-list
|
||||||
|
|
||||||
|
#define check_null(p) ((p)==0)
|
||||||
|
#define set_null(p) ((p)=0)
|
||||||
|
|
||||||
|
#define queue_push_nz(f,l,n,next,zchk,zset) (zchk(f)?\
|
||||||
|
(((f)=(l)=(n)), zset((n)->next)):\
|
||||||
|
((l)->next=(n),(l)=(n),zset((n)->next)))
|
||||||
|
|
||||||
|
#define queue_push(f,l,n) queue_push_nz(f,l,n,next,check_null,set_null)
|
||||||
|
#define stack_push(f,n,next) ((n)->next=(f), (f)=(n))
|
||||||
|
|
||||||
#endif // BASE_H
|
#endif // BASE_H
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
|
|
||||||
internal Table
|
|
||||||
hash_store_initialize(void)
|
|
||||||
{
|
|
||||||
Table result = {0};
|
|
||||||
|
|
||||||
result.ptr_arena = arena_initialize(KB(1));
|
|
||||||
result.str8_arena = arena_initialize(KB(1));
|
|
||||||
|
|
||||||
result.str8_ptr = arena_push(result.ptr_arena, String8);
|
|
||||||
result.str8_count = 1;
|
|
||||||
result.str8_ptr[0] = str8_lit("");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Key
|
|
||||||
hash_store_string8_to_key(Table *table, String8 value)
|
|
||||||
{
|
|
||||||
Key result = 0;
|
|
||||||
u32 count = table->str8_count;
|
|
||||||
result = count;
|
|
||||||
|
|
||||||
String8 *str8_ptr = table->str8_ptr;
|
|
||||||
for (u32 index = 0; index < count; index += 1, str8_ptr += 1)
|
|
||||||
{
|
|
||||||
if (string8_match(*str8_ptr, value))
|
|
||||||
{
|
|
||||||
result = index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == count)
|
|
||||||
{
|
|
||||||
String8 *new_str8 = arena_push(table->ptr_arena, String8);
|
|
||||||
new_str8->content =
|
|
||||||
arena_push_array(table->str8_arena, u8, value.length);
|
|
||||||
|
|
||||||
memory_copy(new_str8->content, value.content, value.length);
|
|
||||||
table->str8_count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal String8
|
|
||||||
hash_store_string8_from_key(Table *table, Key index)
|
|
||||||
{
|
|
||||||
String8 result = {0};
|
|
||||||
|
|
||||||
if (index < table->str8_count)
|
|
||||||
{
|
|
||||||
result = table->str8_ptr[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
#ifndef HASH_TABLE_H
|
|
||||||
#define HASH_TABLE_H
|
|
||||||
|
|
||||||
typedef u32 Key;
|
|
||||||
|
|
||||||
typedef struct Table Table;
|
|
||||||
struct Table
|
|
||||||
{
|
|
||||||
Arena *ptr_arena;
|
|
||||||
Arena *str8_arena;
|
|
||||||
|
|
||||||
String8 *str8_ptr;
|
|
||||||
u32 str8_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
internal Table hash_store_initialize(void);
|
|
||||||
|
|
||||||
internal String8 hash_store_string8_from_key(Table *table, Key index);
|
|
||||||
internal Key hash_store_string8_to_key(Table *table, String8 value);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
|
||||||
|
internal Key
|
||||||
|
hash_store_hash(String8 data)
|
||||||
|
{
|
||||||
|
Key result = {0};
|
||||||
|
|
||||||
|
u64 hash = 5381;
|
||||||
|
for(u64 i = 0; i < data.length; i += 1)
|
||||||
|
{
|
||||||
|
hash = ((hash << 5) + hash) + data.content[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_copy(&result, &hash, sizeof(u64));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Table *
|
||||||
|
hash_store_initialize(void)
|
||||||
|
{
|
||||||
|
Arena *arena = arena_initialize_default();
|
||||||
|
Arena *str8_arena = arena_initialize_default();
|
||||||
|
|
||||||
|
Table *table = arena_push(arena, Table);
|
||||||
|
table->arena = arena;
|
||||||
|
table->str8_arena = str8_arena;
|
||||||
|
table->slots_count = 200;
|
||||||
|
|
||||||
|
table->slots = arena_push_array(arena, TableSlot, table->slots_count);
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Key
|
||||||
|
hash_store_string8_to_key(Table *table, String8 data)
|
||||||
|
{
|
||||||
|
Key result = hash_store_hash(data);
|
||||||
|
u64 slot_idx = result.U32[0]%table->slots_count;
|
||||||
|
|
||||||
|
TableNode *node = arena_push(table->arena, TableNode);
|
||||||
|
node->data.content = arena_push_array(table->str8_arena, char, data.length);
|
||||||
|
node->data.length = data.length;
|
||||||
|
node->key = result;
|
||||||
|
|
||||||
|
memory_copy(&node->data.content, &data.content, data.length);
|
||||||
|
|
||||||
|
TableSlot *slot = &table->slots[slot_idx];
|
||||||
|
queue_push(slot->first, slot->last, node);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
hash_store_string8_from_key(Table *table, Key key)
|
||||||
|
{
|
||||||
|
String8 result = {0};
|
||||||
|
u64 slot_idx = key.U32[0]%table->slots_count;
|
||||||
|
TableSlot *slot = &table->slots[slot_idx];
|
||||||
|
|
||||||
|
for (TableNode *n = slot->first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if (key.U32[1] == n->key.U32[1])
|
||||||
|
{
|
||||||
|
result = n->data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef HASH_TABLE_H
|
||||||
|
#define HASH_TABLE_H
|
||||||
|
|
||||||
|
typedef struct Key Key;
|
||||||
|
struct Key
|
||||||
|
{
|
||||||
|
u32 U32[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct TableNode TableNode;
|
||||||
|
struct TableNode
|
||||||
|
{
|
||||||
|
TableNode *next;
|
||||||
|
String8 data;
|
||||||
|
Key key;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct TableSlot TableSlot;
|
||||||
|
struct TableSlot
|
||||||
|
{
|
||||||
|
TableNode *first;
|
||||||
|
TableNode *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Table Table;
|
||||||
|
struct Table
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
Arena *str8_arena;
|
||||||
|
|
||||||
|
TableSlot *slots;
|
||||||
|
u64 slots_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal Table * hash_store_initialize(void);
|
||||||
|
|
||||||
|
internal Key hash_store_string8_to_key(Table *table, String8 data);
|
||||||
|
|
||||||
|
#endif
|
28
src/main.c
28
src/main.c
|
@ -1,32 +1,28 @@
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
#include "win32_platform.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "hash-store.h"
|
#include "hash_store.h"
|
||||||
|
|
||||||
|
#include "win32_platform.c"
|
||||||
#include "arena.c"
|
#include "arena.c"
|
||||||
#include "string.c"
|
#include "string.c"
|
||||||
#include "hash-store.c"
|
#include "hash_store.c"
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
Table store = hash_store_initialize();
|
Table *table = hash_store_initialize();
|
||||||
Key a = hash_store_string8_to_key(&store, str8_lit("Hello"));
|
|
||||||
Key b = hash_store_string8_to_key(&store, str8_lit("Beautiful"));
|
|
||||||
Key c = hash_store_string8_to_key(&store, str8_lit("World"));
|
|
||||||
|
|
||||||
String8 str_a = hash_store_string8_from_key(&store, a);
|
String8 str8_1 = str8_lit("Hello world");
|
||||||
String8 str_b = hash_store_string8_from_key(&store, b);
|
String8 str8_2 = str8_lit("ayenooo");
|
||||||
String8 str_c = hash_store_string8_from_key(&store, c);
|
|
||||||
|
|
||||||
ASSERT(hash_store_string8_to_key(&store, str8_lit("Hello")) == a);
|
Key key1 = hash_store_string8_to_key(table, str8_1);
|
||||||
ASSERT(hash_store_string8_to_key(&store, str8_lit("Beautiful")) == b);
|
Key key2 = hash_store_string8_to_key(table, str8_2);
|
||||||
ASSERT(hash_store_string8_to_key(&store, str8_lit("World")) == c);
|
Key key3 = hash_store_string8_to_key(table, str8_1);
|
||||||
|
|
||||||
ASSERT(string8_match(hash_store_string8_from_key(&store, a), str8_lit("Hello")));
|
String8 string = hash_store_string8_from_key(table, key2);
|
||||||
ASSERT(string8_match(hash_store_string8_from_key(&store, b), str8_lit("Beautiful")));
|
printf("%.*s\n", (i32) string.length, string.content);
|
||||||
ASSERT(string8_match(hash_store_string8_from_key(&store, c), str8_lit("World")));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct String8
|
||||||
internal String8 str8_init(u8 *cstring, u64 length);
|
internal String8 str8_init(u8 *cstring, u64 length);
|
||||||
#define str8_lit(cstring) \
|
#define str8_lit(cstring) \
|
||||||
str8_init((u8*)(cstring), sizeof(cstring) - 1)
|
str8_init((u8*)(cstring), sizeof(cstring) - 1)
|
||||||
|
#define str8_lit_comp(cstring) {(u8*)(cstring), sizeof(cstring) - 1}
|
||||||
|
|
||||||
internal u8 string8_match(String8 a, String8 b);
|
internal u8 string8_match(String8 a, String8 b);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
internal void *
|
||||||
|
platform_memory_reserve(u64 size)
|
||||||
|
{
|
||||||
|
void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal b8
|
||||||
|
platform_memory_commit(void *ptr, u64 size)
|
||||||
|
{
|
||||||
|
b32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
platform_memory_decommit(void *ptr, u64 size)
|
||||||
|
{
|
||||||
|
VirtualFree(ptr, size, MEM_DECOMMIT);
|
||||||
|
};
|
||||||
|
|
||||||
|
internal void
|
||||||
|
platform_memory_release(void *ptr, u64 size)
|
||||||
|
{
|
||||||
|
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal u64
|
||||||
|
platform_get_page_size(void)
|
||||||
|
{
|
||||||
|
SYSTEM_INFO sysinfo = {0};
|
||||||
|
GetSystemInfo(&sysinfo);
|
||||||
|
return sysinfo.dwPageSize;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef WIN32_PLATFORM_H
|
||||||
|
#define WIN32_PLATFORM_H
|
||||||
|
|
||||||
|
#undef internal
|
||||||
|
#include <Windows.h>
|
||||||
|
#define internal static
|
||||||
|
|
||||||
|
//= rhjr: platform memory management
|
||||||
|
|
||||||
|
internal void * platform_memory_reserve(u64 size);
|
||||||
|
internal b8 platform_memory_commit(void *ptr, u64 size);
|
||||||
|
internal void platform_memory_decommit(void *ptr, u64 size);
|
||||||
|
internal void platform_memory_release(void *ptr, u64 size);
|
||||||
|
|
||||||
|
internal u64 platform_get_page_size(void);
|
||||||
|
|
||||||
|
#endif // WIN32_PLATFORM_H
|
Loading…
Reference in New Issue
Block a user