Copy thread implementation using C11 threads.h
This commit is contained in:
parent
c4b801b761
commit
a3f00a7b22
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@ include common.mk
|
||||||
|
|
||||||
all: server
|
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 $< $@
|
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
|
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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue