2018-02-12 04:34:32 +00:00
|
|
|
#include "api.h"
|
2018-02-17 17:49:24 +00:00
|
|
|
#include "event/event.h"
|
2019-05-02 22:09:30 +00:00
|
|
|
#include "filesystem/filesystem.h"
|
2018-04-15 04:36:24 +00:00
|
|
|
#include "thread/thread.h"
|
2019-04-05 11:32:58 +00:00
|
|
|
#include "thread/channel.h"
|
2018-02-12 04:34:32 +00:00
|
|
|
|
2018-02-17 17:18:08 +00:00
|
|
|
static int threadRunner(void* data) {
|
|
|
|
Thread* thread = (Thread*) data;
|
|
|
|
|
2018-02-26 08:59:03 +00:00
|
|
|
lovrRetain(thread);
|
2018-02-17 17:18:08 +00:00
|
|
|
mtx_lock(&thread->lock);
|
|
|
|
thread->running = true;
|
|
|
|
thread->error = NULL;
|
|
|
|
mtx_unlock(&thread->lock);
|
|
|
|
|
|
|
|
// Lua state
|
2018-09-26 17:39:17 +00:00
|
|
|
lua_State* L = luaL_newstate();
|
2018-02-17 17:18:08 +00:00
|
|
|
luaL_openlibs(L);
|
2018-09-26 17:39:17 +00:00
|
|
|
lovrSetErrorCallback((lovrErrorHandler) luax_vthrow, L);
|
2018-02-17 17:18:08 +00:00
|
|
|
|
2018-11-14 02:18:59 +00:00
|
|
|
lua_getglobal(L, "package");
|
|
|
|
lua_getfield(L, -1, "preload");
|
|
|
|
luaL_register(L, NULL, lovrModules);
|
|
|
|
lua_pop(L, 2);
|
|
|
|
|
2019-05-02 22:09:30 +00:00
|
|
|
if (luaL_loadbuffer(L, thread->body->data, thread->body->size, "thread") || lua_pcall(L, 0, 0, 0)) {
|
2018-02-17 17:18:08 +00:00
|
|
|
thread->error = lua_tostring(L, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
mtx_lock(&thread->lock);
|
|
|
|
thread->running = false;
|
|
|
|
mtx_unlock(&thread->lock);
|
2019-04-05 10:41:03 +00:00
|
|
|
lovrRelease(Thread, thread);
|
2018-02-17 17:49:24 +00:00
|
|
|
|
|
|
|
if (thread->error) {
|
2018-07-26 20:40:15 +00:00
|
|
|
lovrEventPush((Event) {
|
|
|
|
.type = EVENT_THREAD_ERROR,
|
|
|
|
.data.thread = { thread, strdup(thread->error) }
|
|
|
|
});
|
2018-02-19 18:47:11 +00:00
|
|
|
lua_close(L);
|
2018-02-17 17:49:24 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-02-19 18:47:11 +00:00
|
|
|
lua_close(L);
|
2018-02-17 17:18:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrThreadNewThread(lua_State* L) {
|
2019-05-02 22:09:30 +00:00
|
|
|
Blob* blob = luax_totype(L, 1, Blob);
|
|
|
|
if (!blob) {
|
|
|
|
size_t length;
|
|
|
|
const char* str = lua_tolstring(L, 1, &length);
|
|
|
|
if (memchr(str, '\n', MIN(1024, length))) {
|
|
|
|
blob = lovrBlobCreate(strdup(str), length, "thread code");
|
|
|
|
} else {
|
|
|
|
void* code = lovrFilesystemRead(str, -1, &length);
|
|
|
|
lovrAssert(code, "Could not read thread code from %s", str);
|
|
|
|
blob = lovrBlobCreate(code, length, str);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lovrRetain(blob);
|
|
|
|
}
|
|
|
|
Thread* thread = lovrThreadCreate(threadRunner, blob);
|
2018-07-25 03:10:30 +00:00
|
|
|
luax_pushobject(L, thread);
|
2019-04-05 10:41:03 +00:00
|
|
|
lovrRelease(Thread, thread);
|
2019-05-02 22:09:30 +00:00
|
|
|
lovrRelease(Blob, blob);
|
2018-02-12 04:34:32 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrThreadGetChannel(lua_State* L) {
|
2018-02-18 00:51:32 +00:00
|
|
|
const char* name = luaL_checkstring(L, 1);
|
|
|
|
Channel* channel = lovrThreadGetChannel(name);
|
2018-07-25 03:10:30 +00:00
|
|
|
luax_pushobject(L, channel);
|
2018-02-18 00:51:32 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static const luaL_Reg lovrThreadModule[] = {
|
2018-02-12 07:03:43 +00:00
|
|
|
{ "newThread", l_lovrThreadNewThread },
|
2018-02-18 00:51:32 +00:00
|
|
|
{ "getChannel", l_lovrThreadGetChannel },
|
2018-02-12 04:34:32 +00:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
2018-09-27 01:27:38 +00:00
|
|
|
|
|
|
|
int luaopen_lovr_thread(lua_State* L) {
|
|
|
|
lua_newtable(L);
|
|
|
|
luaL_register(L, NULL, lovrThreadModule);
|
2019-04-05 10:48:36 +00:00
|
|
|
luax_registertype(L, Thread);
|
|
|
|
luax_registertype(L, Channel);
|
2018-12-19 08:04:55 +00:00
|
|
|
if (lovrThreadModuleInit()) {
|
|
|
|
luax_atexit(L, lovrThreadModuleDestroy);
|
2018-11-19 16:08:56 +00:00
|
|
|
}
|
2018-09-27 01:27:38 +00:00
|
|
|
return 1;
|
|
|
|
}
|