mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-02 20:18:12 +00:00
initial upload
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): State Safety Helper
|
||||
|
||||
internal B32
|
||||
demon_access_begin(void){
|
||||
B32 result = 0;
|
||||
if (demon_primary_thread){
|
||||
Assert(demon_run_state);
|
||||
result = 1;
|
||||
}
|
||||
else{
|
||||
os_mutex_take(demon_state_mutex);
|
||||
if (demon_run_state){
|
||||
os_mutex_drop(demon_state_mutex);
|
||||
}
|
||||
else{
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
demon_access_end(void){
|
||||
if (!demon_primary_thread){
|
||||
os_mutex_drop(demon_state_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Entity System
|
||||
|
||||
internal void
|
||||
demon_common_init(void){
|
||||
// access control mechanism
|
||||
demon_state_mutex = os_mutex_alloc();
|
||||
|
||||
// time
|
||||
demon_time = 1;
|
||||
|
||||
// setup arena
|
||||
demon_ent_arena = arena_alloc();
|
||||
|
||||
// setup map
|
||||
demon_ent_map = push_array(demon_ent_arena, DEMON_Map, 1);
|
||||
demon_ent_map->bucket_count = 4093;
|
||||
demon_ent_map->buckets = push_array(demon_ent_arena, DEMON_MapSlot*, demon_ent_map->bucket_count);
|
||||
|
||||
// setup entity memory
|
||||
U64 reserve_size_unaligned = (DEMON_ENTITY_CAP)*sizeof(DEMON_Entity);
|
||||
U64 reserve_size = AlignPow2(reserve_size_unaligned, DEMON_ENTITY_CMT_SIZE);
|
||||
demon_ent_cmt = demon_ent_pos = demon_ent_base = (DEMON_Entity*)os_reserve(reserve_size);
|
||||
demon_ent_opl = demon_ent_base + (reserve_size/sizeof(DEMON_Entity));
|
||||
|
||||
Assert(demon_ent_base != 0);
|
||||
|
||||
// setup root
|
||||
demon_ent_root = demon_ent_alloc();
|
||||
demon_ent_root->kind = DEMON_EntityKind_Root;
|
||||
}
|
||||
|
||||
internal DEMON_Entity*
|
||||
demon_ent_alloc(void){
|
||||
DEMON_Entity *result = demon_ent_free;
|
||||
if (result != 0){
|
||||
SLLStackPop(demon_ent_free);
|
||||
}
|
||||
else{
|
||||
if (demon_ent_pos < demon_ent_opl){
|
||||
if (ensure_commit(&demon_ent_cmt, demon_ent_pos + 1, DEMON_ENTITY_CMT_SIZE)){
|
||||
result = demon_ent_pos;
|
||||
demon_ent_pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result != 0){
|
||||
U32 gen = result->gen;
|
||||
MemoryZeroStruct(result);
|
||||
result->gen = gen;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
//- handle <-> entity pointer
|
||||
|
||||
internal DEMON_Entity*
|
||||
demon_ent_ptr_from_handle(DEMON_Handle handle){
|
||||
Assert(demon_ent_base != 0);
|
||||
DEMON_Entity *result = 0;
|
||||
U32 index = (U32)(handle & 0xFFFFFFFF);
|
||||
U64 count = (U64)(demon_ent_pos - demon_ent_base);
|
||||
if (0 < index && index < count){
|
||||
DEMON_Entity *entity = demon_ent_base + index;
|
||||
U32 gen = (U32)(handle >> 32);
|
||||
if (gen == entity->gen){
|
||||
result = entity;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal DEMON_Handle
|
||||
demon_ent_handle_from_ptr(DEMON_Entity *entity){
|
||||
Assert(demon_ent_base != 0);
|
||||
DEMON_Handle result = {0};
|
||||
if (demon_ent_base < entity && entity < demon_ent_pos){
|
||||
U32 index = (U32)(entity - demon_ent_base);
|
||||
U64 gen = entity->gen;
|
||||
result = (gen << 32) | index;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
//- high level entity alloc,init,release
|
||||
|
||||
internal DEMON_Entity*
|
||||
demon_ent_new(DEMON_Entity *parent, DEMON_EntityKind kind, U64 id){
|
||||
Assert(demon_ent_base != 0);
|
||||
DEMON_Entity *result = demon_ent_alloc();
|
||||
if (result != 0){
|
||||
result->kind = kind;
|
||||
result->id = id;
|
||||
result->arch = parent->arch;
|
||||
result->parent = parent;
|
||||
DLLPushBack(parent->first, parent->last, result);
|
||||
demon_ent_map_save(kind, id, result);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
demon_ent_release_single(DEMON_Entity *entity){
|
||||
switch (entity->kind){
|
||||
case DEMON_EntityKind_Process: demon_proc_count -= 1; break;
|
||||
case DEMON_EntityKind_Thread: demon_thread_count -= 1; break;
|
||||
case DEMON_EntityKind_Module: demon_module_count -= 1; break;
|
||||
}
|
||||
demon_accel_free(entity);
|
||||
demon_os_entity_cleanup(entity);
|
||||
DEMON_MapRef ref = demon_ent_map_find(entity->kind, entity->id);
|
||||
demon_ent_map_erase(ref);
|
||||
entity->gen += 1;
|
||||
}
|
||||
|
||||
internal void
|
||||
demon_ent_release_children(DEMON_Entity *root){
|
||||
Assert(demon_ent_base != 0);
|
||||
if (root->first != 0){
|
||||
for (DEMON_Entity *node = root->first;
|
||||
node != 0;
|
||||
node = node->next){
|
||||
demon_ent_release_children(node);
|
||||
demon_ent_release_single(node);
|
||||
}
|
||||
root->last->next = demon_ent_free;
|
||||
demon_ent_free = root->first;
|
||||
root->first = 0;
|
||||
root->last = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
demon_ent_release_root_and_children(DEMON_Entity *root){
|
||||
Assert(demon_ent_base != 0);
|
||||
Assert(root->parent != 0);
|
||||
|
||||
// release children
|
||||
demon_ent_release_children(root);
|
||||
|
||||
// release root
|
||||
DEMON_Entity *parent = root->parent;
|
||||
demon_ent_release_single(root);
|
||||
DLLRemove(parent->first, parent->last, root);
|
||||
SLLStackPush(demon_ent_free, root);
|
||||
}
|
||||
|
||||
//- entity map
|
||||
|
||||
internal U64
|
||||
demon_ent_map_hash(U16 kind, U64 id){
|
||||
U64 result = ((U64)kind << 32) ^ id;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
demon_ent_map_save(U16 kind, U64 id, DEMON_Entity *entity){
|
||||
Assert(demon_ent_base != 0);
|
||||
DEMON_Map *map = demon_ent_map;
|
||||
|
||||
// allocate a new slot
|
||||
DEMON_MapSlot *slot = map->free_slots;
|
||||
if (slot != 0){
|
||||
SLLStackPop(map->free_slots);
|
||||
}
|
||||
else{
|
||||
slot = push_array_no_zero(demon_ent_arena, DEMON_MapSlot, 1);
|
||||
}
|
||||
|
||||
// fill slot
|
||||
slot->kind = kind;
|
||||
slot->id = id;
|
||||
slot->entity = entity;
|
||||
|
||||
// insert into bucket
|
||||
U64 hash = demon_ent_map_hash(kind, id);
|
||||
U64 bucket_index = hash%map->bucket_count;
|
||||
SLLStackPush(map->buckets[bucket_index], slot);
|
||||
}
|
||||
|
||||
internal DEMON_MapRef
|
||||
demon_ent_map_find(U16 kind, U64 id){
|
||||
Assert(demon_ent_base != 0);
|
||||
DEMON_Map *map = demon_ent_map;
|
||||
|
||||
// scan bucket
|
||||
DEMON_MapRef result = {0};
|
||||
U64 hash = demon_ent_map_hash(kind, id);
|
||||
U64 bucket_index = hash%map->bucket_count;
|
||||
for (DEMON_MapSlot **ptr = &map->buckets[bucket_index], *slot = 0;
|
||||
*ptr != 0;
|
||||
ptr = &slot->next){
|
||||
slot = *ptr;
|
||||
if (slot->kind == kind && slot->id == id){
|
||||
result.slot = slot;
|
||||
result.ptr_to_slot = ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal DEMON_Entity*
|
||||
demon_ent_map_entity_from_id(U16 kind, U64 id){
|
||||
DEMON_Entity *result = 0;
|
||||
DEMON_MapRef ref = demon_ent_map_find(kind, id);
|
||||
if (ref.slot != 0){
|
||||
result = ref.slot->entity;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
demon_ent_map_erase(DEMON_MapRef ref){
|
||||
Assert(demon_ent_base != 0);
|
||||
DEMON_Map *map = demon_ent_map;
|
||||
|
||||
// move slot to free list
|
||||
if (ref.slot != 0){
|
||||
*ref.ptr_to_slot = ref.slot->next;
|
||||
SLLStackPush(map->free_slots, ref.slot);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Event Helpers
|
||||
|
||||
internal DEMON_Event*
|
||||
demon_push_event(Arena *arena, DEMON_EventList *list, DEMON_EventKind kind){
|
||||
DEMON_EventNode *n = push_array(arena, DEMON_EventNode, 1);
|
||||
DEMON_Event *result = &n->v;
|
||||
SLLQueuePush(list->first, list->last, n);
|
||||
list->count += 1;
|
||||
result->kind = kind;
|
||||
return(result);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user