151 lines
4.3 KiB
C++
151 lines
4.3 KiB
C++
#pragma once
|
|
#include "dqn.h"
|
|
|
|
/*
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// $$$$$$$$\ $$\ $$$$$$\
|
|
// \__$$ __|$$ | $$ __$$\
|
|
// $$ | $$ | $$ / \__|
|
|
// $$ | $$ | \$$$$$$\
|
|
// $$ | $$ | \____$$\
|
|
// $$ | $$ | $$\ $$ |
|
|
// $$ | $$$$$$$$\\$$$$$$ |
|
|
// \__| \________|\______/
|
|
//
|
|
// dqn_tls.cpp
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
// NOTE: [$TCTX] DN_TLS /////////////////////////////////////////////////////////////////
|
|
DN_TLSTMem::DN_TLSTMem(DN_TLS *tls, uint8_t arena_index, DN_TLSPushTMem push_tmem)
|
|
{
|
|
DN_ASSERT(arena_index == DN_TLSArena_TMem0 || arena_index == DN_TLSArena_TMem1);
|
|
arena = tls->arenas + arena_index;
|
|
temp_mem = DN_Arena_TempMemBegin(arena);
|
|
destructed = false;
|
|
push_arena = push_tmem;
|
|
if (push_arena)
|
|
DN_TLS_PushArena(arena);
|
|
}
|
|
|
|
DN_TLSTMem::~DN_TLSTMem()
|
|
{
|
|
DN_ASSERT(destructed == false);
|
|
DN_Arena_TempMemEnd(temp_mem);
|
|
destructed = true;
|
|
if (push_arena)
|
|
DN_TLS_PopArena();
|
|
}
|
|
|
|
DN_API void DN_TLS_Init(DN_TLS *tls)
|
|
{
|
|
DN_CHECK(tls);
|
|
if (tls->init)
|
|
return;
|
|
|
|
DN_FOR_UINDEX (index, DN_TLSArena_Count) {
|
|
DN_Arena *arena = tls->arenas + index;
|
|
switch (DN_CAST(DN_TLSArena)index) {
|
|
default: *arena = DN_Arena_InitSize(DN_MEGABYTES(4), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break;
|
|
case DN_TLSArena_ErrorSink: *arena = DN_Arena_InitSize(DN_KILOBYTES(64), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break;
|
|
case DN_TLSArena_Count: DN_INVALID_CODE_PATH; break;
|
|
}
|
|
}
|
|
|
|
tls->thread_id = DN_OS_ThreadID();
|
|
tls->err_sink.arena = tls->arenas + DN_TLSArena_ErrorSink;
|
|
tls->init = true;
|
|
}
|
|
|
|
DN_API void DN_TLS_Deinit(DN_TLS *tls)
|
|
{
|
|
tls->init = false;
|
|
tls->err_sink = {};
|
|
tls->arena_stack_index = {};
|
|
DN_FOR_UINDEX(index, DN_TLSArena_Count)
|
|
{
|
|
DN_Arena *arena = tls->arenas + index;
|
|
DN_Arena_Deinit(arena);
|
|
}
|
|
}
|
|
|
|
DN_API DN_TLS *DN_TLS_Get()
|
|
{
|
|
DN_TLS *result = g_dn_os_thread_tls;
|
|
DN_ASSERT(
|
|
g_dn_core->init &&
|
|
"Library context must be be initialised first by calling DN_Library_Init. This "
|
|
"initialises the main thread's TLS for you (no need to call DN_OS_ThreadSetTLS on main)");
|
|
|
|
DN_ASSERT(result &&
|
|
"Thread must be assigned the TLS with DN_OS_ThreadSetTLS. If the library is "
|
|
"initialised, then, this thread was created without calling the set TLS function "
|
|
"for the spawned thread.");
|
|
return result;
|
|
}
|
|
|
|
DN_API DN_Arena *DN_TLS_Arena()
|
|
{
|
|
DN_TLS *tls = DN_TLS_Get();
|
|
DN_Arena *result = tls->arenas + DN_TLSArena_Main;
|
|
return result;
|
|
}
|
|
|
|
// TODO: Is there a way to handle conflict arenas without the user needing to
|
|
// manually pass it in?
|
|
DN_API DN_TLSTMem DN_TLS_GetTMem(void const *conflict_arena, DN_TLSPushTMem push_tmem)
|
|
{
|
|
DN_TLS *tls = DN_TLS_Get();
|
|
uint8_t tls_index = (uint8_t)-1;
|
|
for (uint8_t index = DN_TLSArena_TMem0; index <= DN_TLSArena_TMem1; index++) {
|
|
DN_Arena *arena = tls->arenas + index;
|
|
if (!conflict_arena || arena != conflict_arena) {
|
|
tls_index = index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DN_ASSERT(tls_index != (uint8_t)-1);
|
|
return DN_TLSTMem(tls, tls_index, push_tmem);
|
|
}
|
|
|
|
DN_API void DN_TLS_PushArena(DN_Arena *arena)
|
|
{
|
|
DN_ASSERT(arena);
|
|
DN_TLS *tls = DN_TLS_Get();
|
|
DN_ASSERT(tls->arena_stack_index < DN_ARRAY_UCOUNT(tls->arena_stack));
|
|
tls->arena_stack[tls->arena_stack_index++] = arena;
|
|
}
|
|
|
|
DN_API void DN_TLS_PopArena()
|
|
{
|
|
DN_TLS *tls = DN_TLS_Get();
|
|
DN_ASSERT(tls->arena_stack_index > 0);
|
|
tls->arena_stack_index--;
|
|
}
|
|
|
|
DN_API DN_Arena *DN_TLS_TopArena()
|
|
{
|
|
DN_TLS *tls = DN_TLS_Get();
|
|
DN_Arena *result = nullptr;
|
|
if (tls->arena_stack_index)
|
|
result = tls->arena_stack[tls->arena_stack_index - 1];
|
|
return result;
|
|
}
|
|
|
|
DN_API void DN_TLS_BeginFrame(DN_Arena *frame_arena)
|
|
{
|
|
DN_TLS *tls = DN_TLS_Get();
|
|
tls->frame_arena = frame_arena;
|
|
}
|
|
|
|
DN_API DN_Arena *DN_TLS_FrameArena()
|
|
{
|
|
DN_TLS *tls = DN_TLS_Get();
|
|
DN_Arena *result = tls->frame_arena;
|
|
return result;
|
|
}
|
|
|