Get latest changes from LPP bot

This commit is contained in:
2025-06-03 16:26:40 +10:00
parent 2371297dda
commit b1394e6416
29 changed files with 2644 additions and 290 deletions
+114
View File
@@ -0,0 +1,114 @@
#define DN_ASYNC_CPP
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#include "dn_async.h"
static DN_I32 DN_ASYNC_ThreadEntryPoint_(DN_OSThread *thread)
{
DN_OS_ThreadSetName(DN_FStr8_ToStr8(&thread->name));
DN_ASYNCCore *async = DN_CAST(DN_ASYNCCore *) thread->user_context;
DN_Ring *ring = &async->ring;
for (;;) {
DN_OS_SemaphoreWait(&async->worker_sem, UINT32_MAX);
if (async->join_threads)
break;
DN_ASYNCJob job = {};
for (DN_OS_MutexScope(&async->ring_mutex)) {
if (DN_Ring_HasData(ring, sizeof(job))) {
DN_Ring_Read(ring, &job, sizeof(job));
break;
}
}
if (job.work.func) {
DN_OS_ConditionVariableBroadcast(&async->ring_write_cv); // Resume any blocked ring write(s)
DN_Atomic_AddU32(&async->busy_threads, 1);
job.work.func(job.work.input);
DN_Atomic_SubU32(&async->busy_threads, 1);
if (job.completion_sem.handle != 0)
DN_OS_SemaphoreIncrement(&job.completion_sem, 1);
}
}
return 0;
}
DN_API void DN_ASYNC_Init(DN_ASYNCCore *async, char *base, DN_USize base_size, DN_OSThread *threads, DN_U32 threads_size)
{
DN_Assert(async);
async->ring.size = base_size;
async->ring.base = base;
async->ring_mutex = DN_OS_MutexInit();
async->ring_write_cv = DN_OS_ConditionVariableInit();
async->worker_sem = DN_OS_SemaphoreInit(0);
async->thread_count = threads_size;
async->threads = threads;
for (DN_ForIndexU(index, async->thread_count)) {
DN_OSThread *thread = async->threads + index;
thread->name = DN_FStr8_InitF<64>("ASYNC W%zu", index);
DN_OS_ThreadInit(thread, DN_ASYNC_ThreadEntryPoint_, async);
}
}
DN_API void DN_ASYNC_Deinit(DN_ASYNCCore *async)
{
DN_Assert(async);
DN_Atomic_SetValue32(&async->join_threads, true);
DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count);
for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count))
DN_OS_ThreadDeinit(it.data);
}
static bool DN_ASYNC_QueueJob_(DN_ASYNCCore *async, DN_ASYNCJob const *job, DN_U64 wait_time_ms) {
DN_U64 end_time_ms = DN_OS_DateUnixTimeMs() + wait_time_ms;
bool result = false;
for (DN_OS_MutexScope(&async->ring_mutex)) {
for (;;) {
if (DN_Ring_HasSpace(&async->ring, sizeof(*job))) {
DN_Ring_WriteStruct(&async->ring, job);
result = true;
break;
}
DN_OS_ConditionVariableWaitUntil(&async->ring_write_cv, &async->ring_mutex, end_time_ms);
if (DN_OS_DateUnixTimeMs() >= end_time_ms)
break;
}
}
if (result)
DN_OS_SemaphoreIncrement(&async->worker_sem, 1); // Flag that a job is available
return result;
}
DN_API bool DN_ASYNC_QueueWork(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms)
{
DN_ASYNCJob job = {};
job.work.func = func;
job.work.input = input;
bool result = DN_ASYNC_QueueJob_(async, &job, wait_time_ms);
return result;
}
DN_API DN_OSSemaphore DN_ASYNC_QueueTask(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms)
{
DN_OSSemaphore result = DN_OS_SemaphoreInit(0);
DN_ASYNCJob job = {};
job.work.func = func;
job.work.input = input;
job.completion_sem = result;
DN_ASYNC_QueueJob_(async, &job, wait_time_ms);
return result;
}
DN_API void DN_ASYNC_WaitTask(DN_OSSemaphore *sem, DN_U32 timeout_ms)
{
DN_OS_SemaphoreWait(sem, timeout_ms);
DN_OS_SemaphoreDeinit(sem);
}
+52
View File
@@ -0,0 +1,52 @@
#if !defined(DN_ASYNC_H)
#define DN_ASYNC_H
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
enum DN_ASYNCPriority
{
DN_ASYNCPriority_Low,
DN_ASYNCPriority_High,
DN_ASYNCPriority_Count,
};
struct DN_ASYNCCore
{
DN_OSMutex ring_mutex;
DN_OSConditionVariable ring_write_cv;
DN_OSSemaphore worker_sem;
DN_Ring ring;
DN_OSThread *threads;
DN_U32 thread_count;
DN_U32 busy_threads;
DN_U32 join_threads;
};
typedef void(DN_ASYNCWorkFunc)(void *input);
struct DN_ASYNCWork
{
DN_ASYNCWorkFunc *func;
void *input;
void *output;
};
struct DN_ASYNCJob
{
DN_ASYNCWork work;
DN_OSSemaphore completion_sem;
};
struct DN_ASYNCTask
{
DN_ASYNCWork work;
};
DN_API void DN_ASYNC_Init (DN_ASYNCCore *async, char *base, DN_USize base_size, DN_OSThread *threads, DN_U32 threads_size);
DN_API void DN_ASYNC_Deinit (DN_ASYNCCore *async);
DN_API bool DN_ASYNC_QueueWork(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms);
DN_API DN_OSSemaphore DN_ASYNC_QueueTask(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms);
DN_API void DN_ASYNC_WaitTask (DN_OSSemaphore *sem, DN_U32 timeout_ms);
#endif // DN_ASYNC_H
+12 -13
View File
@@ -142,22 +142,21 @@ DN_API void DN_PCG32_Advance (DN_PCG32 *rng
#if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
#define DN_JSONBuilder_Object(builder) \
DN_DEFER_LOOP(DN_JSONBuilder_ObjectBegin(builder), \
DN_JSONBuilder_ObjectEnd(builder))
#define DN_JSONBuilder_Object(builder) \
DN_DeferLoop(DN_JSONBuilder_ObjectBegin(builder), \
DN_JSONBuilder_ObjectEnd(builder))
#define DN_JSONBuilder_ObjectNamed(builder, name) \
DN_DEFER_LOOP(DN_JSONBuilder_ObjectBeginNamed(builder, name), \
DN_JSONBuilder_ObjectEnd(builder))
#define DN_JSONBuilder_ObjectNamed(builder, name) \
DN_DeferLoop(DN_JSONBuilder_ObjectBeginNamed(builder, name), \
DN_JSONBuilder_ObjectEnd(builder))
#define DN_JSONBuilder_Array(builder) \
DN_DEFER_LOOP(DN_JSONBuilder_ArrayBegin(builder), \
DN_JSONBuilder_ArrayEnd(builder))
#define DN_JSONBuilder_ArrayNamed(builder, name) \
DN_DEFER_LOOP(DN_JSONBuilder_ArrayBeginNamed(builder, name), \
DN_JSONBuilder_ArrayEnd(builder))
#define DN_JSONBuilder_Array(builder) \
DN_DeferLoop(DN_JSONBuilder_ArrayBegin(builder), \
DN_JSONBuilder_ArrayEnd(builder))
#define DN_JSONBuilder_ArrayNamed(builder, name) \
DN_DeferLoop(DN_JSONBuilder_ArrayBeginNamed(builder, name), \
DN_JSONBuilder_ArrayEnd(builder))
DN_API DN_JSONBuilder DN_JSONBuilder_Init (DN_Arena *arena, int spaces_per_indent);
DN_API DN_Str8 DN_JSONBuilder_Build (DN_JSONBuilder const *builder, DN_Arena *arena);
+16 -16
View File
@@ -407,22 +407,22 @@ void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site)
json_string_s const *key = curr->name;
if (it->flags & json_parse_flags_allow_location_information) {
json_string_ex_s const *info = DN_CAST(json_string_ex_s const *)key;
DN_Log_TypeFCallSite(DN_LogType_Warning,
call_site,
"Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]",
info->line_no,
info->row_no,
DN_CAST(int)key->string_size,
key->string,
DN_CAST(int)value_type_size,
value_type);
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning),
call_site,
"Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]",
info->line_no,
info->row_no,
DN_CAST(int) key->string_size,
key->string,
DN_CAST(int) value_type_size,
value_type);
} else {
DN_Log_TypeFCallSite(DN_LogType_Warning,
call_site,
"Unknown key-value pair in object [key=%.*s, value=%.*s]",
DN_CAST(int)key->string_size,
key->string,
DN_CAST(int)value_type_size,
value_type);
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning),
call_site,
"Unknown key-value pair in object [key=%.*s, value=%.*s]",
DN_CAST(int) key->string_size,
key->string,
DN_CAST(int) value_type_size,
value_type);
}
}
+62 -8
View File
@@ -1151,8 +1151,8 @@ static DN_UTCore DN_Tests_Intrinsics()
DN_UT_Test(&result, "DN_Atomic_SetValue32")
{
long a = 0;
long b = 111;
DN_U32 a = 0;
DN_U32 b = 111;
DN_Atomic_SetValue32(&a, b);
DN_UT_AssertF(&result, a == b, "a: %ld, b: %ld", a, b);
}
@@ -1574,6 +1574,8 @@ static DN_UTCore DN_Tests_M4()
static DN_UTCore DN_Tests_OS()
{
DN_UTCore result = DN_UT_Init();
#if defined(DN_OS_INC_CPP) || 1
DN_UT_LogF(&result, "DN_OS\n");
{
DN_UT_Test(&result, "Generate secure RNG bytes with nullptr")
@@ -1690,6 +1692,58 @@ static DN_UTCore DN_Tests_OS()
}
}
DN_UT_LogF(&result, "\nSemaphore\n");
{
DN_OSSemaphore sem = DN_OS_SemaphoreInit(0);
DN_UT_Test(&result, "Wait timeout")
{
DN_U64 begin = DN_OS_PerfCounterNow();
DN_OSSemaphoreWaitResult wait_result = DN_OS_SemaphoreWait(&sem, 100 /*timeout_ms*/);
DN_U64 end = DN_OS_PerfCounterNow();
DN_UT_AssertF(&result, wait_result == DN_OSSemaphoreWaitResult_Timeout, "Received wait result %zu", wait_result);
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(begin, end);
DN_UT_AssertF(&result, elapsed_ms >= 100, "Expected to sleep for >= 100ms, slept %f ms", elapsed_ms);
}
DN_UT_Test(&result, "Wait success")
{
DN_OS_SemaphoreIncrement(&sem, 1);
DN_OSSemaphoreWaitResult wait_result = DN_OS_SemaphoreWait(&sem, 0 /*timeout_ms*/);
DN_UT_AssertF(&result, wait_result == DN_OSSemaphoreWaitResult_Success, "Received wait result %zu", wait_result);
}
DN_OS_SemaphoreDeinit(&sem);
}
DN_UT_LogF(&result, "\nMutex\n");
{
DN_OSMutex mutex = DN_OS_MutexInit();
DN_UT_Test(&result, "Lock")
{
DN_OS_MutexLock(&mutex);
DN_OS_MutexUnlock(&mutex);
}
DN_OS_MutexDeinit(&mutex);
}
DN_UT_LogF(&result, "\nCondition Variable\n");
{
DN_OSMutex mutex = DN_OS_MutexInit();
DN_OSConditionVariable cv = DN_OS_ConditionVariableInit();
DN_UT_Test(&result, "Lock and timeout")
{
DN_U64 begin = DN_OS_PerfCounterNow();
DN_OS_ConditionVariableWait(&cv, &mutex, 100 /*sleep_ms*/);
DN_U64 end = DN_OS_PerfCounterNow();
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(begin, end);
DN_UT_AssertF(&result, elapsed_ms >= 100, "Expected to sleep for >= 100ms, slept %f ms", elapsed_ms);
}
DN_OS_MutexDeinit(&mutex);
DN_OS_ConditionVariableDeinit(&cv);
}
#endif
return result;
}
@@ -2372,25 +2426,25 @@ static DN_UTCore DN_Tests_Win()
DN_UT_Test(&result, "Str8 to Str16")
{
DN_Str16 str_result = DN_Win_Str8ToStr16(tmem.arena, input8);
DN_Str16 str_result = DN_W32_Str8ToStr16(tmem.arena, input8);
DN_UT_Assert(&result, str_result == input16);
}
DN_UT_Test(&result, "Str16 to Str8")
{
DN_Str8 str_result = DN_Win_Str16ToStr8(tmem.arena, input16);
DN_Str8 str_result = DN_W32_Str16ToStr8(tmem.arena, input16);
DN_UT_Assert(&result, str_result == input8);
}
DN_UT_Test(&result, "Str16 to Str8: Null terminates string")
{
int size_required = DN_Win_Str16ToStr8Buffer(input16, nullptr, 0);
int size_required = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0);
char *string = DN_Arena_NewArray(tmem.arena, char, size_required + 1, DN_ZeroMem_No);
// Fill the string with error sentinels
DN_Memset(string, 'Z', size_required + 1);
int size_returned = DN_Win_Str16ToStr8Buffer(input16, string, size_required + 1);
int size_returned = DN_W32_Str16ToStr8Buffer(input16, string, size_required + 1);
char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
DN_UT_AssertF(&result, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned);
@@ -2400,8 +2454,8 @@ static DN_UTCore DN_Tests_Win()
DN_UT_Test(&result, "Str16 to Str8: Arena null terminates string")
{
DN_Str8 string8 = DN_Win_Str16ToStr8(tmem.arena, input16);
int size_returned = DN_Win_Str16ToStr8Buffer(input16, nullptr, 0);
DN_Str8 string8 = DN_W32_Str16ToStr8(tmem.arena, input16);
int size_returned = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0);
char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
DN_UT_AssertF(&result, DN_CAST(int) string8.size == size_returned, "string_size: %d, result: %d", DN_CAST(int) string8.size, size_returned);