Import latest revision of dqn lib from CSIGHT

This commit is contained in:
doylet 2024-03-19 23:11:00 +11:00
parent 7f2a0152e0
commit 158d058d5d
16 changed files with 270 additions and 81 deletions

View File

@ -71,7 +71,7 @@ void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...);
#define Dqn_CppForBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginForBLock(cpp, fmt, ##__VA_ARGS__), true); \
(Dqn_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false))

View File

@ -220,7 +220,7 @@ DQN_API void Dqn_Arena_Pop(Dqn_Arena *arena, uint64_t amount)
Dqn_Arena_PopTo(arena, pop_to);
}
DQN_API uint64_t Dqn_Arena_Pos(Dqn_Arena *arena)
DQN_API uint64_t Dqn_Arena_Pos(Dqn_Arena const *arena)
{
uint64_t result = (arena && arena->curr) ? arena->curr->reserve_sum + arena->curr->used : 0;
return result;
@ -231,6 +231,18 @@ DQN_API void Dqn_Arena_Clear(Dqn_Arena *arena)
Dqn_Arena_PopTo(arena, 0);
}
DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr)
{
bool result = false;
uintptr_t uint_ptr = DQN_CAST(uintptr_t)ptr;
for (Dqn_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; ) {
uintptr_t begin = DQN_CAST(uintptr_t) block + DQN_ARENA_HEADER_SIZE;
uintptr_t end = begin + block->reserve;
result = uint_ptr >= begin && uint_ptr <= end;
}
return result;
}
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin(Dqn_Arena *arena)
{
Dqn_ArenaTempMem result = {};

View File

@ -145,8 +145,9 @@ DQN_API void * Dqn_Arena_AllocContiguous (Dqn_Arena *arena,
DQN_API void * Dqn_Arena_Copy (Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align);
DQN_API void Dqn_Arena_PopTo (Dqn_Arena *arena, uint64_t init_used);
DQN_API void Dqn_Arena_Pop (Dqn_Arena *arena, uint64_t amount);
DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena *arena);
DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena const *arena);
DQN_API void Dqn_Arena_Clear (Dqn_Arena *arena);
DQN_API bool Dqn_Arena_OwnsPtr (Dqn_Arena const *arena, void *ptr);
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin (Dqn_Arena *arena);
DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem mem);
#define Dqn_Arena_New(arena, T, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)

View File

@ -419,6 +419,12 @@ DQN_API Dqn_ErrorSink *Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode mode)
return result;
}
DQN_API bool Dqn_ErrorSink_HasError(Dqn_ErrorSink *error)
{
bool result = error && error->stack->error;
return result;
}
DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End(Dqn_Arena *arena, Dqn_ErrorSink *error)
{
Dqn_ErrorSinkNode result = {};
@ -445,7 +451,7 @@ DQN_API bool Dqn_ErrorSink_EndAndLogError(Dqn_ErrorSink *error, Dqn_Str8 error_m
Dqn_ErrorSinkNode node = Dqn_ErrorSink_End(scratch.arena, error);
if (node.error) {
if (Dqn_Str8_HasData(error_msg)) {
Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s. %.*s", DQN_STR_FMT(error_msg), DQN_STR_FMT(node.msg));
Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s: %.*s", DQN_STR_FMT(error_msg), DQN_STR_FMT(node.msg));
} else {
Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s", DQN_STR_FMT(node.msg));
}
@ -475,8 +481,10 @@ DQN_API bool Dqn_ErrorSink_EndAndLogErrorF(Dqn_ErrorSink *error, DQN_FMT_ATTRIB
DQN_API void Dqn_ErrorSink_EndAndExitIfErrorFV(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, va_list args)
{
if (Dqn_ErrorSink_EndAndLogErrorFV(error, fmt, args))
if (Dqn_ErrorSink_EndAndLogErrorFV(error, fmt, args)) {
DQN_DEBUG_BREAK;
Dqn_OS_Exit(exit_code);
}
}
DQN_API void Dqn_ErrorSink_EndAndExitIfErrorF(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, ...)
@ -500,7 +508,7 @@ DQN_API void Dqn_ErrorSink_MakeFV_(Dqn_ErrorSink *error, uint32_t error_code, DQ
node->error = true;
node->call_site = Dqn_ThreadContext_Get()->call_site;
if (node->mode == Dqn_ErrorSinkMode_ExitOnError)
Dqn_ErrorSink_EndAndExitIfErrorF(error, error_code, "Fatal error encountered: (%u) %.*s", error_code, DQN_STR_FMT(node->msg));
Dqn_ErrorSink_EndAndExitIfErrorF(error, error_code, "Fatal error %u", error_code);
}
}

View File

@ -285,8 +285,8 @@
} while (0)
#endif
#define DQN_INVALID_CODE_PATHF(fmt, ...) DQN_ASSERTF(0, fmt, ##__VA_ARGS__)
#define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered")
#define DQN_INVALID_CODE_PATHF(fmt, ...) DQN_HARD_ASSERTF(0, fmt, ##__VA_ARGS__)
#define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered")
// NOTE: Check macro ///////////////////////////////////////////////////////////////////////////////
#define DQN_CHECK(expr) DQN_CHECKF(expr, "")
@ -621,6 +621,7 @@ DQN_API void Dqn_Log_FCallSite
// NOTE: [$ERRS] Dqn_ErrorSink /////////////////////////////////////////////////////////////////////
DQN_API Dqn_ErrorSink * Dqn_ErrorSink_Begin (Dqn_ErrorSinkMode mode);
DQN_API bool Dqn_ErrorSink_HasError (Dqn_ErrorSink *error);
DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End (Dqn_Arena *arena, Dqn_ErrorSink *error);
DQN_API bool Dqn_ErrorSink_EndAndLogError (Dqn_ErrorSink *error, Dqn_Str8 error_msg);
DQN_API bool Dqn_ErrorSink_EndAndLogErrorFV (Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args);

View File

@ -105,6 +105,9 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error)
DQN_ARRAY_UCOUNT(DQN_CGEN_TABLE_TYPE_LIST),
"Table 'type' specified invalid value");
table->type = DQN_CAST(Dqn_CGenTableType) table_type_validator.enum_val;
DQN_ASSERT(table->type <= Dqn_CGenTableType_Count);
cgen->table_counts[table->type]++;
} break;
}
}
@ -454,6 +457,7 @@ DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTabl
// NOTE: Lookup the table in this row that we will code generate from. Not
// applicable when we are doing builtin types as the types are just put
// in-line into the code generation table itself.
it->cgen_table = cgen_table;
it->cgen_table_row = cgen_table->rows + it->row_index++;
if (cgen_table->type != Dqn_CGenTableType_CodeGenBuiltinTypes) {
Dqn_CGenTableColumn cgen_table_column = it->cgen_table_row->columns[cgen_table->column_indexes[Dqn_CGenTableHeaderType_Table]];
@ -752,7 +756,7 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
}
Dqn_CppBlock(cpp, ";\n\n", "Dqn_TypeInfo const g_%.*s_types[] =", DQN_STR_FMT(emit_prefix)) {
Dqn_CppLine(cpp, "{DQN_STR8(\"\"),%*sDqn_TypeKind_Nil, /*fields*/ NULL, /*count*/ 0},", 1 + longest_name_across_all_tables, "");
Dqn_CppLine(cpp, "{DQN_STR8(\"\"),%*sDqn_TypeKind_Nil, 0, /*fields*/ NULL, /*count*/ 0},", 1 + longest_name_across_all_tables, "");
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
@ -794,16 +798,45 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
}
Dqn_CppLine(cpp,
"{DQN_STR8(\"%.*s\"),%*s%.*s, %s/*fields*/ %.*s,%*s/*count*/ %.*s},",
"{DQN_STR8(\"%.*s\"),%*s%.*s, %ssizeof(%.*s),%*s/*fields*/ %.*s,%*s/*count*/ %.*s},",
DQN_STR_FMT(type_name),
name_padding, "",
DQN_STR_FMT(type_info_kind),
type_info_kind_padding,
DQN_STR_FMT(type_name),
name_padding, "",
DQN_STR_FMT(fields),
fields_padding, "",
DQN_STR_FMT(fields_count));
}
}
}
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
if (table->type != Dqn_CGenTableType_CodeGenEnum)
continue;
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
Dqn_CppStructBlock(cpp, "%.*sStr8ToEnumResult", DQN_STR_FMT(type_name)) {
Dqn_CppLine(cpp, "bool success;");
Dqn_CppLine(cpp, "%.*s value;", DQN_STR_FMT(type_name));
}
Dqn_CppFuncBlock(cpp, "%.*sStr8ToEnumResult %.*s_Str8ToEnum(Dqn_Str8 string)", DQN_STR_FMT(type_name), DQN_STR_FMT(type_name)) {
Dqn_CppLine(cpp, "%.*sStr8ToEnumResult result = {};", DQN_STR_FMT(type_name));
Dqn_CppForBlock(cpp, "Dqn_usize index = 0; !result.success && index < DQN_ARRAY_UCOUNT(g_%.*s_type_fields); index++", DQN_STR_FMT(type_name)) {
Dqn_CppIfChain(cpp) {
Dqn_CppLine(cpp, "Dqn_TypeField field = g_%.*s_type_fields[index];", DQN_STR_FMT(type_name));
Dqn_CppIfOrElseIfBlock(cpp, "string == field.name") {
Dqn_CppLine(cpp, "result.success = true;");
Dqn_CppLine(cpp, "result.value = (%.*s)index;", DQN_STR_FMT(type_name));
}
}
}
Dqn_CppLine(cpp, "return result;");
}
}
}
}
}

View File

@ -43,6 +43,7 @@ enum Dqn_CGenTableType
Dqn_CGenTableType_CodeGenBuiltinTypes,
Dqn_CGenTableType_CodeGenStruct,
Dqn_CGenTableType_CodeGenEnum,
Dqn_CGenTableType_Count,
};
enum Dqn_CGenTableRowTagType
@ -123,6 +124,7 @@ struct Dqn_CGen
MD_Map table_map;
Dqn_CGenTable *first_table;
Dqn_CGenTable *last_table;
Dqn_usize table_counts[Dqn_CGenTableType_Count];
};
struct Dqn_CGenMapNodeToEnum
@ -133,6 +135,7 @@ struct Dqn_CGenMapNodeToEnum
struct Dqn_CGenLookupTableIterator
{
Dqn_CGenTable *cgen_table;
Dqn_CGenTableRow *cgen_table_row;
Dqn_CGenTableColumn cgen_table_column[Dqn_CGenTableHeaderType_Count];
Dqn_CGenTable *table;

View File

@ -400,11 +400,11 @@ template <typename T> T *Dqn_CArray_InsertArray(T *data, Dqn_usize *size, Dqn_us
Dqn_usize clamped_index = DQN_MIN(index, *size);
if (clamped_index != *size) {
char const *src = DQN_CAST(char *)(data + clamped_index);
char const *dest = DQN_CAST(char *)(data + (clamped_index + count));
char const *end = DQN_CAST(char *)(data + (*size));
Dqn_usize bytes_to_move = end - src;
DQN_MEMMOVE(DQN_CAST(void *)dest, src, bytes_to_move);
char const *src = DQN_CAST(char *)(data + clamped_index);
char const *dest = DQN_CAST(char *)(data + (clamped_index + count));
char const *end = DQN_CAST(char *)(data + (*size));
Dqn_usize bytes_to_move = end - src;
DQN_MEMMOVE(DQN_CAST(void *) dest, src, bytes_to_move);
}
result = data + clamped_index;
@ -561,7 +561,7 @@ template <typename T> T *Dqn_VArray_InsertArray(Dqn_VArray<T> *array, Dqn_usize
T *result = nullptr;
if (!Dqn_VArray_IsValid(array))
return result;
if (Dqn_VArray_Reserve(array, count))
if (Dqn_VArray_Reserve(array, array->size + count))
result = Dqn_CArray_InsertArray(array->data, &array->size, array->max, index, items, count);
return result;
}

View File

@ -523,8 +523,7 @@ DQN_API uint32_t Dqn_Safe_SubU32(uint32_t a, uint32_t b)
return result;
}
// NOTE: Dqn_Safe_SaturateCastUSizeToI*
// -----------------------------------------------------------------------------
// NOTE: Dqn_Safe_SaturateCastUSizeToI* ////////////////////////////////////////////////////////////
// INT*_MAX literals will be promoted to the type of uintmax_t as uintmax_t is
// the highest possible rank (unsigned > signed).
DQN_API int Dqn_Safe_SaturateCastUSizeToInt(Dqn_usize val)
@ -557,8 +556,7 @@ DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64(Dqn_usize val)
return result;
}
// NOTE: Dqn_Safe_SaturateCastUSizeToU*
// -----------------------------------------------------------------------------
// NOTE: Dqn_Safe_SaturateCastUSizeToU* ////////////////////////////////////////////////////////////
// Both operands are unsigned and the lowest rank operand will be promoted to
// match the highest rank operand.
DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8(Dqn_usize val)
@ -624,8 +622,7 @@ DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32(uint64_t val)
return result;
}
// NOTE: Dqn_Safe_SaturateCastISizeToI*
// -----------------------------------------------------------------------------
// NOTE: Dqn_Safe_SaturateCastISizeToI* ////////////////////////////////////////////////////////////
// Both operands are signed so the lowest rank operand will be promoted to
// match the highest rank operand.
DQN_API int Dqn_Safe_SaturateCastISizeToInt(Dqn_isize val)
@ -663,8 +660,7 @@ DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64(Dqn_isize val)
return result;
}
// NOTE: Dqn_Safe_SaturateCastISizeToU*
// -----------------------------------------------------------------------------
// NOTE: Dqn_Safe_SaturateCastISizeToU* ////////////////////////////////////////////////////////////
// If the value is a negative integer, we clamp to 0. Otherwise, we know that
// the value is >=0, we can upcast safely to bounds check against the maximum
// allowed value.
@ -728,8 +724,7 @@ DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64(Dqn_isize val)
return result;
}
// NOTE: Dqn_Safe_SaturateCastI64To*
// -----------------------------------------------------------------------------
// NOTE: Dqn_Safe_SaturateCastI64To* ///////////////////////////////////////////////////////////////
// Both operands are signed so the lowest rank operand will be promoted to
// match the highest rank operand.
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize(int64_t val)
@ -760,8 +755,79 @@ DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32(int64_t val)
return result;
}
// NOTE: Dqn_Safe_SaturateCastIntTo*
// -----------------------------------------------------------------------------
DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt(int64_t val)
{
unsigned int result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT_MAX))
result = DQN_CAST(unsigned int) val;
else
result = UINT_MAX;
}
return result;
}
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize(int64_t val)
{
Dqn_usize result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= DQN_USIZE_MAX))
result = DQN_CAST(Dqn_usize) val;
else
result = DQN_USIZE_MAX;
}
return result;
}
DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8(int64_t val)
{
uint8_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT8_MAX))
result = DQN_CAST(uint8_t) val;
else
result = UINT8_MAX;
}
return result;
}
DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16(int64_t val)
{
uint16_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT16_MAX))
result = DQN_CAST(uint16_t) val;
else
result = UINT16_MAX;
}
return result;
}
DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32(int64_t val)
{
uint32_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT32_MAX))
result = DQN_CAST(uint32_t) val;
else
result = UINT32_MAX;
}
return result;
}
DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64(int64_t val)
{
uint64_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT64_MAX))
result = DQN_CAST(uint64_t) val;
else
result = UINT64_MAX;
}
return result;
}
// NOTE: Dqn_Safe_SaturateCastIntTo* ///////////////////////////////////////////////////////////////
DQN_API int8_t Dqn_Safe_SaturateCastIntToI8(int val)
{
DQN_CHECK(val >= INT8_MIN && val <= INT8_MAX);
@ -1260,87 +1326,113 @@ void Dqn_Profiler_Dump(uint64_t tsc_per_second)
// NOTE: [$JOBQ] Dqn_JobQueue ///////////////////////////////////////////////////////////////////////
DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit()
{
Dqn_JobQueueSPMC result = {};
result.thread_wait_for_job_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/);
result.wait_for_completion_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/);
result.mutex = Dqn_OS_MutexInit();
Dqn_JobQueueSPMC result = {};
result.thread_wait_for_job_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/);
result.wait_for_completion_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/);
result.complete_queue_write_semaphore = Dqn_OS_SemaphoreInit(DQN_ARRAY_UCOUNT(result.complete_queue));
result.mutex = Dqn_OS_MutexInit();
return result;
}
DQN_API bool Dqn_OS_JobQueueSPMCAddArray(Dqn_JobQueueSPMC *job_queue, Dqn_Job *jobs, uint32_t count)
DQN_API bool Dqn_OS_JobQueueSPMCAddArray(Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, uint32_t count)
{
if (!job_queue)
if (!queue)
return false;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(job_queue->jobs) - 1;
uint32_t read_index = job_queue->read_index;
uint32_t write_index = job_queue->write_index;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1;
uint32_t read_index = queue->read_index;
uint32_t write_index = queue->write_index;
uint32_t size = write_index - read_index;
if ((size + count) > DQN_ARRAY_UCOUNT(job_queue->jobs))
if ((size + count) > DQN_ARRAY_UCOUNT(queue->jobs))
return false;
for (size_t offset = 0; offset < count; offset++) {
uint32_t wrapped_write_index = (write_index + offset) & pot_mask;
job_queue->jobs[wrapped_write_index] = jobs[offset];
queue->jobs[wrapped_write_index] = jobs[offset];
}
Dqn_OS_MutexLock(&job_queue->mutex);
job_queue->write_index += count;
Dqn_OS_SemaphoreIncrement(&job_queue->thread_wait_for_job_semaphore, count);
Dqn_OS_MutexUnlock(&job_queue->mutex);
Dqn_OS_MutexLock(&queue->mutex);
queue->write_index += count;
Dqn_OS_SemaphoreIncrement(&queue->thread_wait_for_job_semaphore, count);
Dqn_OS_MutexUnlock(&queue->mutex);
return true;
}
DQN_API bool Dqn_OS_JobQueueSPMCAdd(Dqn_JobQueueSPMC *job_queue, Dqn_Job job)
DQN_API bool Dqn_OS_JobQueueSPMCAdd(Dqn_JobQueueSPMC *queue, Dqn_Job job)
{
bool result = Dqn_OS_JobQueueSPMCAddArray(job_queue, &job, 1);
bool result = Dqn_OS_JobQueueSPMCAddArray(queue, &job, 1);
return result;
}
DQN_API int32_t Dqn_OS_JobQueueSPMCThread(Dqn_OSThread *thread)
{
Dqn_JobQueueSPMC *job_queue = DQN_CAST(Dqn_JobQueueSPMC *) thread->user_context;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(job_queue->jobs) - 1;
Dqn_JobQueueSPMC *queue = DQN_CAST(Dqn_JobQueueSPMC *) thread->user_context;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1;
static_assert(DQN_ARRAY_UCOUNT(queue->jobs) == DQN_ARRAY_UCOUNT(queue->complete_queue), "PoT mask is used to mask access to both arrays");
for (;;) {
Dqn_OS_SemaphoreWait(&job_queue->thread_wait_for_job_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
if (job_queue->quit)
Dqn_OS_SemaphoreWait(&queue->thread_wait_for_job_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
if (queue->quit)
break;
DQN_ASSERT(job_queue->read_index != job_queue->write_index);
DQN_ASSERT(queue->read_index != queue->write_index);
Dqn_OS_MutexLock(&job_queue->mutex);
uint32_t wrapped_read_index = job_queue->read_index & pot_mask;
Dqn_Job job = job_queue->jobs[wrapped_read_index];
job_queue->read_index += 1;
Dqn_OS_MutexUnlock(&job_queue->mutex);
Dqn_OS_MutexLock(&queue->mutex);
uint32_t wrapped_read_index = queue->read_index & pot_mask;
Dqn_Job job = queue->jobs[wrapped_read_index];
queue->read_index += 1;
Dqn_OS_MutexUnlock(&queue->mutex);
job.func(job.user_context);
Dqn_Arena_Deinit(job.arena);
Dqn_OS_MutexLock(&job_queue->mutex);
job_queue->complete_index += 1;
if (job_queue->complete_index == job_queue->write_index && job_queue->threads_waiting_for_completion) {
Dqn_OS_SemaphoreIncrement(&job_queue->wait_for_completion_semaphore,
job_queue->threads_waiting_for_completion);
job_queue->threads_waiting_for_completion = 0;
if (job.add_to_completion_queue) {
Dqn_OS_SemaphoreWait(&queue->complete_queue_write_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
Dqn_OS_MutexLock(&queue->mutex);
queue->complete_queue[(queue->complete_write_index++ & pot_mask)] = job;
Dqn_OS_MutexUnlock(&queue->mutex);
Dqn_OS_SemaphoreIncrement(&queue->complete_queue_write_semaphore, 1);
}
Dqn_OS_MutexUnlock(&job_queue->mutex);
Dqn_OS_MutexLock(&queue->mutex);
queue->finish_index += 1;
if (queue->finish_index == queue->write_index && queue->threads_waiting_for_completion) {
Dqn_OS_SemaphoreIncrement(&queue->wait_for_completion_semaphore,
queue->threads_waiting_for_completion);
queue->threads_waiting_for_completion = 0;
}
Dqn_OS_MutexUnlock(&queue->mutex);
}
return job_queue->quit_exit_code;
return queue->quit_exit_code;
}
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion(Dqn_JobQueueSPMC *job_queue)
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion(Dqn_JobQueueSPMC *queue)
{
Dqn_OS_MutexLock(&job_queue->mutex);
if (job_queue->read_index == job_queue->write_index) {
Dqn_OS_MutexUnlock(&job_queue->mutex);
Dqn_OS_MutexLock(&queue->mutex);
if (queue->read_index == queue->write_index) {
Dqn_OS_MutexUnlock(&queue->mutex);
return;
}
job_queue->threads_waiting_for_completion++;
Dqn_OS_MutexUnlock(&job_queue->mutex);
queue->threads_waiting_for_completion++;
Dqn_OS_MutexUnlock(&queue->mutex);
Dqn_OS_SemaphoreWait(&job_queue->wait_for_completion_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
Dqn_OS_SemaphoreWait(&queue->wait_for_completion_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
}
DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs(Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size)
{
Dqn_usize result = 0;
if (!queue || !jobs || jobs_size <= 0)
return result;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1;
Dqn_OS_MutexLock(&queue->mutex);
while (queue->complete_read_index < queue->complete_write_index && result < jobs_size) {
jobs[result++] = queue->complete_queue[(queue->complete_read_index++ & pot_mask)];
}
Dqn_OS_MutexUnlock(&queue->mutex);
return result;
}

View File

@ -202,8 +202,10 @@ struct Dqn_Profiler
typedef void (Dqn_JobQueueFunc)(void *user_context);
struct Dqn_Job
{
bool add_to_completion_queue;
Dqn_Arena *arena;
Dqn_JobQueueFunc *func;
uint32_t user_tag;
void *user_context;
};
@ -214,12 +216,17 @@ struct Dqn_JobQueueSPMC
Dqn_OSSemaphore wait_for_completion_semaphore;
uint32_t threads_waiting_for_completion;
Dqn_Job jobs[32];
Dqn_Job jobs[64];
Dqn_b32 quit;
uint32_t quit_exit_code;
uint32_t volatile read_index;
uint32_t volatile complete_index;
uint32_t volatile finish_index;
uint32_t volatile write_index;
Dqn_OSSemaphore complete_queue_write_semaphore;
Dqn_Job complete_queue[64];
uint32_t volatile complete_read_index;
uint32_t volatile complete_write_index;
};
// NOTE: [$DLIB] Dqn_Library ///////////////////////////////////////////////////////////////////////
@ -408,6 +415,13 @@ DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8 (int64_t va
DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16 (int64_t val);
DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32 (int64_t val);
DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt (int64_t val);
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize (int64_t val);
DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8 (int64_t val);
DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16 (int64_t val);
DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32 (int64_t val);
DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64 (int64_t val);
DQN_API int8_t Dqn_Safe_SaturateCastIntToI8 (int val);
DQN_API int16_t Dqn_Safe_SaturateCastIntToI16 (int val);
DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8 (int val);
@ -433,10 +447,11 @@ DQN_API void Dqn_Profiler_Dump (uint64_t t
// NOTE: [$JOBQ] Dqn_JobQueue ///////////////////////////////////////////////////////////////////////
DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit ();
DQN_API bool Dqn_OS_JobQueueSPMCAddArray (Dqn_JobQueueSPMC *job_queue, Dqn_Job *jobs, uint32_t count);
DQN_API bool Dqn_OS_JobQueueSPMCAdd (Dqn_JobQueueSPMC *job_queue, Dqn_Job job);
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion (Dqn_JobQueueSPMC *job_queue);
DQN_API bool Dqn_OS_JobQueueSPMCAddArray (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, uint32_t count);
DQN_API bool Dqn_OS_JobQueueSPMCAdd (Dqn_JobQueueSPMC *queue, Dqn_Job job);
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion (Dqn_JobQueueSPMC *queue);
DQN_API int32_t Dqn_OS_JobQueueSPMCThread (Dqn_OSThread *thread);
DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size);
// NOTE: Dqn_Library ///////////////////////////////////////////////////////////////////////////////
DQN_API Dqn_Library * Dqn_Library_Init (Dqn_LibraryOnInit on_init);

View File

@ -285,7 +285,6 @@ DQN_API bool Dqn_OS_SecureRNGBytes (void *buffer, uint
DQN_API Dqn_Str8 Dqn_OS_EXEPath (Dqn_Arena *arena);
DQN_API Dqn_Str8 Dqn_OS_EXEDir (Dqn_Arena *arena);
DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds);
// NOTE: Counters //////////////////////////////////////////////////////////////////////////////////
DQN_API uint64_t Dqn_OS_PerfCounterNow ();
DQN_API uint64_t Dqn_OS_PerfCounterFrequency();
@ -345,7 +344,7 @@ DQN_API Dqn_Str8 Dqn_OS_PathConvertF (Dqn_Arena *arena
#define Dqn_OS_PathBuild(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, Dqn_OSPathSeparatorString)
// NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_OS_Exit (uint32_t exit_code);
DQN_API void Dqn_OS_Exit (int32_t exit_code);
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait (Dqn_OSExecAsyncHandle handle);
DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync (Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir);
DQN_API Dqn_OSExecResult Dqn_OS_Exec (Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir);

View File

@ -526,9 +526,9 @@ DQN_API void Dqn_OS_FileClose(Dqn_OSFile *file)
#endif // !defined(DQN_NO_OS_FILE_API)
// NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_OS_Exit(uint32_t exit_code)
DQN_API void Dqn_OS_Exit(int32_t exit_code)
{
exit(exit_code);
exit(DQN_CAST(int)exit_code);
}
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle)

View File

@ -545,9 +545,9 @@ DQN_API void Dqn_OS_FileClose(Dqn_OSFile *file)
#endif // !defined(DQN_NO_OS_FILE_API)
// NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_OS_Exit(uint32_t exit_code)
DQN_API void Dqn_OS_Exit(int32_t exit_code)
{
ExitProcess(exit_code);
ExitProcess(DQN_CAST(UINT)exit_code);
}
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle)

View File

@ -119,6 +119,12 @@ DQN_API Dqn_Str8 Dqn_Str8_Advance(Dqn_Str8 string, Dqn_usize amount)
return result;
}
DQN_API Dqn_Str8 Dqn_Str8_NextLine(Dqn_Str8 string)
{
Dqn_Str8 result = Dqn_Str8_BinarySplit(string, DQN_STR8("\n")).rhs;
return result;
}
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size)
{
Dqn_Str8BinarySplitResult result = {};
@ -839,6 +845,22 @@ DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8Builder_BuildSlice(Dqn_Str8Builder const *bu
return result;
}
DQN_API void Dqn_Str8Builder_PrintF(Dqn_Str8Builder const *builder)
{
for (Dqn_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next)
Dqn_Print(link->string);
}
DQN_API void Dqn_Str8Builder_PrintLnF(Dqn_Str8Builder const *builder)
{
for (Dqn_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next) {
if (link->next) {
Dqn_Print(link->string);
} else {
Dqn_Print_Ln(link->string);
}
}
}
// NOTE: [$CHAR] Dqn_Char //////////////////////////////////////////////////////////////////////////
DQN_API bool Dqn_Char_IsAlphabet(char ch)

View File

@ -152,6 +152,7 @@ DQN_API Dqn_Str8 Dqn_Str8_Copy
DQN_API Dqn_Str8 Dqn_Str8_Slice (Dqn_Str8 string, Dqn_usize offset, Dqn_usize size);
DQN_API Dqn_Str8 Dqn_Str8_Advance (Dqn_Str8 string, Dqn_usize amount);
DQN_API Dqn_Str8 Dqn_Str8_NextLine (Dqn_Str8 string);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplit (Dqn_Str8 string, Dqn_Str8 find);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitReverseArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size);
@ -206,6 +207,7 @@ DQN_API bool Dqn_Str8Builder_Ap
DQN_API Dqn_Str8 Dqn_Str8Builder_Build (Dqn_Str8Builder const *builder, Dqn_Arena *arena);
DQN_API Dqn_Str8 Dqn_Str8Builder_BuildCRT (Dqn_Str8Builder const *builder);
DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8Builder_BuildSlice (Dqn_Str8Builder const *builder, Dqn_Arena *arena);
DQN_API void Dqn_Str8Builder_PrintF (Dqn_Str8Builder const *builder);
// NOTE: [$FSTR] Dqn_FStr8 //////////////////////////////////////////////////////////////////////
#if !defined(DQN_NO_FSTR8)

View File

@ -39,6 +39,7 @@ struct Dqn_TypeInfo
{
Dqn_Str8 name;
Dqn_TypeKind kind;
Dqn_usize size_of;
Dqn_TypeField const *fields;
uint16_t fields_count;
};