From 109b40bcb4df5fd50c842a331f924884d06c1dc6 Mon Sep 17 00:00:00 2001 From: bjorn Date: Mon, 12 Feb 2018 21:30:00 -0800 Subject: [PATCH] Thread:wait; Thread:getError; Thread:isRunning; --- src/api/types/thread.c | 26 ++++++++++++++++++++++++ src/thread/thread.c | 45 +++++++++++++++++++++++++++++++++++++++--- src/thread/thread.h | 7 +++++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/api/types/thread.c b/src/api/types/thread.c index 0a1f1927..05fc2007 100644 --- a/src/api/types/thread.c +++ b/src/api/types/thread.c @@ -7,7 +7,33 @@ int l_lovrThreadStart(lua_State* L) { return 0; } +int l_lovrThreadWait(lua_State* L) { + Thread* thread = luax_checktype(L, 1, Thread); + lovrThreadWait(thread); + return 0; +} + +int l_lovrThreadGetError(lua_State* L) { + Thread* thread = luax_checktype(L, 1, Thread); + const char* error = lovrThreadGetError(thread); + if (error) { + lua_pushstring(L, error); + } else { + lua_pushnil(L); + } + return 1; +} + +int l_lovrThreadIsRunning(lua_State* L) { + Thread* thread = luax_checktype(L, 1, Thread); + lua_pushboolean(L, thread->running); + return 1; +} + const luaL_Reg lovrThread[] = { { "start", l_lovrThreadStart }, + { "wait", l_lovrThreadWait }, + { "getError", l_lovrThreadGetError }, + { "isRunning", l_lovrThreadIsRunning }, { NULL, NULL } }; diff --git a/src/thread/thread.c b/src/thread/thread.c index bcdf7c98..8f22b7eb 100644 --- a/src/thread/thread.c +++ b/src/thread/thread.c @@ -6,6 +6,12 @@ static int runner(void* data) { Thread* thread = (Thread*) data; + lovrRetain(&thread->ref); + mtx_lock(&thread->lock); + thread->running = true; + thread->error = NULL; + mtx_unlock(&thread->lock); + // Lua state lua_State* L = luaL_newstate(); luaL_openlibs(L); @@ -35,10 +41,16 @@ static int runner(void* data) { //luax_preloadmodule(L, "enet", luaopen_enet); if (luaL_loadbuffer(L, thread->body, strlen(thread->body), "thread") || lua_pcall(L, 0, 0, 0)) { - printf("error running thread\n"); + thread->error = lua_tostring(L, -1); + //lua_getglobal(lovr, "threaderror"); + lovrRelease(&thread->ref); return 1; } + mtx_lock(&thread->lock); + thread->running = false; + mtx_unlock(&thread->lock); + lovrRelease(&thread->ref); return 0; } @@ -47,17 +59,44 @@ Thread* lovrThreadCreate(const char* body) { if (!thread) return NULL; thread->body = body; + thread->error = NULL; + thread->running = false; + mtx_init(&thread->lock, mtx_plain); return thread; } void lovrThreadDestroy(const Ref* ref) { Thread* thread = containerof(ref, Thread); + mtx_destroy(&thread->lock); + thrd_detach(thread->handle); free(thread); } void lovrThreadStart(Thread* thread) { - if (thrd_create(&thread->handle, runner, thread)) { - // + bool running = lovrThreadIsRunning(thread); + + if (running) { + return; + } + + if (thrd_create(&thread->handle, runner, thread) != thrd_success) { + lovrThrow("Could not create thread...sorry"); + return; } } + +void lovrThreadWait(Thread* thread) { + thrd_join(thread->handle, NULL); +} + +bool lovrThreadIsRunning(Thread* thread) { + mtx_lock(&thread->lock); + bool running = thread->running; + mtx_unlock(&thread->lock); + return running; +} + +const char* lovrThreadGetError(Thread* thread) { + return thread->error; +} diff --git a/src/thread/thread.h b/src/thread/thread.h index 469cebbf..fd3cb75b 100644 --- a/src/thread/thread.h +++ b/src/thread/thread.h @@ -1,14 +1,21 @@ #include "util.h" #include "lib/tinycthread/tinycthread.h" +#include #pragma once typedef struct { Ref ref; thrd_t handle; + mtx_t lock; const char* body; + const char* error; + bool running; } Thread; Thread* lovrThreadCreate(const char* body); void lovrThreadDestroy(const Ref* ref); void lovrThreadStart(Thread* thread); +void lovrThreadWait(Thread* thread); +const char* lovrThreadGetError(Thread* thread); +bool lovrThreadIsRunning(Thread* thread);