Copy thread implementation using C11 threads.h

This commit is contained in:
Vftdan 2024-10-25 02:27:30 +02:00
parent c4b801b761
commit a3f00a7b22
2 changed files with 136 additions and 1 deletions

View File

@ -2,7 +2,7 @@ include common.mk
all: server
$(BUILD_DIR)/common/util/thread.o: $(BUILD_DIR)/common/util/thread.posix.o
$(BUILD_DIR)/common/util/thread.o: $(BUILD_DIR)/common/util/thread.std.o
cp $< $@
server: $(BUILD_DIR)/server/main.o $(BUILD_DIR)/common/util/hash_table.o $(BUILD_DIR)/common/util/byte_stream.o $(BUILD_DIR)/common/util/thread.o

View File

@ -0,0 +1,135 @@
#include "thread.h"
#include <threads.h>
#include <errno.h>
#include <assert.h>
typedef struct {
ThreadEntry entry;
ThreadResult error_result;
} NativeEntryArg;
inline static thrd_t
get_handle(Thread wrapper)
{
assert(wrapper.opaque != NULL);
return *(thrd_t*) wrapper.opaque;
}
inline static bool
new_uninitialized(Thread *th)
{
thrd_t *data = T_ALLOC(1, thrd_t);
if (!data) {
return false;
}
*th = (Thread) { .opaque = data };
return true;
}
inline static void
initialize_handle(Thread *th, thrd_t handle)
{
assert(th != NULL);
assert(th->opaque != NULL);
*(thrd_t*) th->opaque = handle;
return;
}
inline static Thread
delete_handle(Thread th)
{
if (!th.opaque) {
return THREAD_NONE;
}
free(th.opaque);
return THREAD_NONE;
}
static int
run_entry(void *arg)
{
assert(arg != NULL);
NativeEntryArg casted_arg = *(NativeEntryArg*) arg;
ThreadEntry entry = casted_arg.entry;
uint32_t error_result = casted_arg.error_result.value;
free(arg);
if (!entry.callback) {
return error_result;
}
ThreadResult result = entry.callback(entry.env);
return result.value;
}
Thread
thread_spawn(ThreadEntry entry, ThreadResult error_result)
{
NativeEntryArg *native_arg = T_ALLOC(1, NativeEntryArg);
if (!native_arg) {
return THREAD_NONE;
}
*native_arg = (NativeEntryArg) {
.entry = entry,
.error_result = error_result,
};
Thread th;
thrd_t handle;
int error;
if (!new_uninitialized(&th)) {
free(native_arg);
return THREAD_NONE;
}
error = thrd_create(&handle, &run_entry, native_arg); // calls free(native_arg) if error == 0
if (error != thrd_success) {
#ifdef ENOMEM
if (error == thrd_nomem) {
errno = ENOMEM;
}
#endif
free(native_arg);
return delete_handle(th);
}
initialize_handle(&th, handle);
return th;
}
Thread
thread_delete_handle(Thread th)
{
return delete_handle(th);
}
bool
thread_join(Thread th, ThreadResult *result_ptr)
{
if (!th.opaque) {
#ifdef EINVAL
errno = EINVAL;
#endif
return false;
}
thrd_t handle = get_handle(th);
int32_t *retval = NULL;
if (result_ptr) {
result_ptr->pointer = NULL;
retval = (int32_t*) &result_ptr->value;
}
int error = thrd_join(handle, retval);
if (error != thrd_success) {
return false;
}
return true;
}
void
thread_exit(ThreadResult result)
{
thrd_exit(result.value);
}
bool
thread_yield()
{
thrd_yield();
return true;
}