Multiple thread backends.

This commit is contained in:
Przemysław Grzywacz
2011-06-08 16:54:35 +02:00
parent 09ed781f66
commit 1d5fca6f46
22 changed files with 1208 additions and 132 deletions
-345
View File
@@ -1,345 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include <common/config.h>
#include "Thread.h"
#ifdef LOVE_BUILD_STANDALONE
extern "C" int luaopen_love(lua_State * L);
#endif // LOVE_BUILD_STANDALONE
extern "C" int luaopen_love_thread(lua_State *L);
namespace love
{
namespace thread
{
namespace sdl
{
int threadfunc(ThreadData *comm)
{
lua_State * L = lua_open();
luaL_openlibs(L);
#ifdef LOVE_BUILD_STANDALONE
love::luax_preload(L, luaopen_love, "love");
luaopen_love(L);
#endif // LOVE_BUILD_STANDALONE
luaopen_love_thread(L);
{
size_t len;
const char *name = comm->getName(&len);
lua_pushlstring(L, name, len);
}
luax_convobj(L, lua_gettop(L), "thread", "getThread");
lua_getglobal(L, "love");
lua_pushvalue(L, -2);
lua_setfield(L, -2, "_curthread");
if(luaL_dostring(L, comm->getCode()) == 1)
{
SDL_mutexP((SDL_mutex*) comm->mutex);
ThreadVariant *v = new ThreadVariant(lua_tostring(L, -1), lua_strlen(L, -1));
comm->setValue("error", v);
v->release();
SDL_mutexV((SDL_mutex*) comm->mutex);
SDL_CondBroadcast((SDL_cond*) comm->cond);
}
lua_close(L);
return 0;
}
ThreadVariant::ThreadVariant(bool boolean)
{
type = BOOLEAN;
data.boolean = boolean;
}
ThreadVariant::ThreadVariant(double number)
{
type = NUMBER;
data.number = number;
}
ThreadVariant::ThreadVariant(const char *string, size_t len)
{
type = STRING;
char *buf = new char[len+1];
memset(buf, 0, len+1);
memcpy(buf, string, len);
data.string.str = buf;
data.string.len = len;
}
ThreadVariant::ThreadVariant(void *userdata)
{
type = LUSERDATA;
data.userdata = userdata;
}
ThreadVariant::ThreadVariant(Type udatatype, void *userdata)
{
type = FUSERDATA;
this->udatatype = udatatype;
Proxy *p = (Proxy *) userdata;
flags = p->flags;
data.userdata = p->data;
((love::Object *) data.userdata)->retain();
}
ThreadVariant::~ThreadVariant()
{
switch(type)
{
case STRING:
delete[] data.string.str;
break;
case FUSERDATA:
((love::Object *) data.userdata)->release();
break;
default:
break;
}
}
ThreadData::ThreadData(const char *name, size_t len, const char *code, void *mutex, void *cond)
: len(len), mutex(mutex), cond(cond)
{
this->name = new char[len+1];
memset(this->name, 0, len+1);
memcpy(this->name, name, len);
if (code)
{
len = strlen(code);
this->code = new char[len+1];
memset(this->code, 0, len+1);
memcpy(this->code, code, len);
}
else
this->code = 0;
}
ThreadData::~ThreadData()
{
delete[] name;
delete[] code;
}
const char *ThreadData::getCode()
{
return code;
}
const char *ThreadData::getName(size_t *len)
{
if (len)
*len = this->len;
return name;
}
ThreadVariant* ThreadData::getValue(const std::string & name)
{
if (shared.count(name) == 0)
return 0;
return shared[name];
}
void ThreadData::clearValue(const std::string & name)
{
if (shared.count(name) == 0)
return;
shared[name]->release();
shared.erase(name);
}
void ThreadData::setValue(const std::string & name, ThreadVariant *v)
{
if (shared.count(name) != 0)
shared[name]->release();
v->retain();
shared[name] = v;
}
Thread::Thread(love::thread::ThreadModule *module, const std::string & name, love::Data *data)
: handle(0), module(module), name(name), isThread(true)
{
module->retain();
unsigned int len = data->getSize();
this->data = new char[len+1];
memset(this->data, 0, len+1);
memcpy(this->data, data->getData(), len);
mutex = SDL_CreateMutex();
cond = SDL_CreateCond();
comm = new ThreadData(name.c_str(), name.length(), this->data, mutex, cond);
}
Thread::Thread(love::thread::ThreadModule *module, const std::string & name)
: handle(0), module(module), name(name), data(0), isThread(false)
{
module->retain();
mutex = SDL_CreateMutex();
cond = SDL_CreateCond();
comm = new ThreadData(name.c_str(), name.length(), NULL, mutex, cond);
}
Thread::~Thread()
{
if (data)
delete[] data;
delete comm;
module->unregister(name);
SDL_DestroyMutex(mutex);
SDL_DestroyCond(cond);
module->release();
}
void Thread::start()
{
if (!handle && isThread)
handle = SDL_CreateThread((int (*)(void*)) threadfunc, (void*) comm);
}
void Thread::kill()
{
if (handle)
{
SDL_mutexP((SDL_mutex *) _gcmutex);
SDL_KillThread(handle);
handle = 0;
SDL_mutexV((SDL_mutex *) _gcmutex);
}
}
void Thread::wait()
{
if (handle)
{
SDL_WaitThread(handle, NULL);
handle = 0;
}
}
void Thread::lock()
{
SDL_mutexP(mutex);
}
void Thread::unlock()
{
SDL_mutexV(mutex);
}
std::string Thread::getName()
{
return name;
}
ThreadVariant *Thread::get(const std::string & name)
{
ThreadVariant *v = comm->getValue(name);
if (v)
v->retain();
return v;
}
ThreadVariant *Thread::demand(const std::string & name)
{
ThreadVariant *v = comm->getValue(name);
while (!v)
{
if (comm->getValue("error"))
return 0;
SDL_CondWait(cond, mutex);
v = comm->getValue(name);
}
v->retain();
return v;
}
void Thread::clear(const std::string & name)
{
comm->clearValue(name);
}
void Thread::set(const std::string & name, ThreadVariant *v)
{
lock(); //this function explicitly locks
comm->setValue(name, v); //because we need
unlock(); //it to unlock here for the cond
SDL_CondBroadcast(cond);
}
ThreadModule::ThreadModule()
{
threads["main"] = new Thread(this, "main");
}
ThreadModule::~ThreadModule()
{
for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++)
{
i->second->kill();
}
}
Thread *ThreadModule::newThread(const std::string & name, love::Data *data)
{
if (threads.count(name) != 0)
return 0;
Thread *t = new Thread(this, name, data);
threads[name] = t;
return t;
}
Thread *ThreadModule::getThread(const std::string & name)
{
if (threads.count(name) == 0)
return 0;
threadlist_t::iterator i = threads.find(name);
return i->second;
}
void ThreadModule::getThreads(Thread ** list)
{
int c = 0;
for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++, c++)
{
list[c] = i->second;
}
}
unsigned ThreadModule::getThreadCount() const
{
return threads.size();
}
void ThreadModule::unregister(const std::string & name)
{
if (threads.count(name) == 0)
return;
threadlist_t::iterator i = threads.find(name);
threads.erase(i);
}
const char *ThreadModule::getName() const
{
return "love.thread.sdl";
}
} // sdl
} // thread
} // love
-147
View File
@@ -1,147 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_THREAD_SDL_THREAD_H
#define LOVE_THREAD_SDL_THREAD_H
// SDL
#include <SDL_thread.h>
#include <SDL_mutex.h>
// STL
#include <map>
#include <string>
// LOVE
#include <thread/ThreadModule.h>
#include <filesystem/File.h>
#include <common/runtime.h>
namespace love
{
namespace thread
{
namespace sdl
{
enum ThreadVariantType
{
UNKNOWN = 0,
BOOLEAN,
NUMBER,
STRING,
LUSERDATA,
FUSERDATA
};
class ThreadVariant : public love::Object
{
public:
ThreadVariant(bool boolean);
ThreadVariant(double number);
ThreadVariant(const char *string, size_t len);
ThreadVariant(void *userdata);
ThreadVariant(Type udatatype, void *userdata);
virtual ~ThreadVariant();
ThreadVariantType type;
union
{
bool boolean;
double number;
struct {
const char *str;
size_t len;
} string;
void *userdata;
} data;
Type udatatype;
bits flags;
};
class ThreadData
{
private:
char *code;
char *name;
std::map<std::string, ThreadVariant*> shared;
size_t len;
public:
ThreadData(const char *name, size_t len, const char *code, void *mutex, void *cond);
~ThreadData();
const char *getCode();
const char *getName(size_t *len = 0);
ThreadVariant* getValue(const std::string & name);
void clearValue(const std::string & name);
void setValue(const std::string & name, ThreadVariant *v);
void *mutex;
void *cond;
};
class Thread : public love::Object
{
private:
SDL_Thread *handle;
love::thread::ThreadModule *module;
ThreadData *comm;
std::string name;
char *data;
SDL_mutex *mutex;
SDL_cond *cond;
bool isThread;
public:
Thread(love::thread::ThreadModule *module, const std::string & name, love::Data *data);
Thread(love::thread::ThreadModule *module, const std::string & name);
virtual ~Thread();
void start();
void kill();
void wait();
std::string getName();
ThreadVariant *get(const std::string & name);
ThreadVariant *demand(const std::string & name);
void clear(const std::string & name);
void set(const std::string & name, ThreadVariant *v);
void lock();
void unlock();
}; // Thread
typedef std::map<std::string, Thread*> threadlist_t;
class ThreadModule : public love::thread::ThreadModule
{
private:
threadlist_t threads;
public:
ThreadModule();
virtual ~ThreadModule();
Thread *newThread(const std::string & name, love::Data *data);
void getThreads(Thread ** list);
Thread *getThread(const std::string & name);
unsigned getThreadCount() const;
void unregister(const std::string & name);
const char *getName() const;
}; // ThreadModule
} // sdl
} // thread
} // love
#endif // LOVE_THREAD_SDL_THREAD_H
+164
View File
@@ -0,0 +1,164 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "threads.h"
namespace love
{
namespace thread
{
Mutex::Mutex() {
mutex = SDL_CreateMutex();
}
Mutex::~Mutex() {
SDL_DestroyMutex(mutex);
}
void Mutex::lock() {
SDL_mutexP(mutex);
}
void Mutex::unlock() {
SDL_mutexV(mutex);
}
int ThreadBase::thread_runner(void* param) {
ThreadBase* thread = (ThreadBase*)param;
thread->main();
return 0;
}
ThreadBase::ThreadBase() : running(false) {
SDL_Thread* thread;
}
ThreadBase::~ThreadBase() {
if (running) {
wait();
}
}
bool ThreadBase::start() {
thread = SDL_CreateThread(thread_runner, this);
if (thread == NULL) {
return false;
} else {
running = true;
return true;
}
}
void ThreadBase::wait() {
SDL_WaitThread(thread, NULL);
running = false;
}
void ThreadBase::kill() {
SDL_KillThread(thread);
running = false;
}
unsigned int ThreadBase::threadId() {
return (unsigned int)SDL_ThreadID();
}
Semaphore::Semaphore(unsigned int initial_value) {
semaphore = SDL_CreateSemaphore(initial_value);
}
Semaphore::~Semaphore() {
SDL_DestroySemaphore(semaphore);
}
unsigned int Semaphore::value() {
return SDL_SemValue(semaphore);
}
void Semaphore::post() {
SDL_SemPost(semaphore);
}
bool Semaphore::wait(int timeout) {
if (timeout < 0) {
return SDL_SemWait(semaphore) ? false : true;
} else if (timeout == 0) {
return SDL_SemTryWait(semaphore) ? false : true;
} else {
int ret = SDL_SemWaitTimeout(semaphore, timeout);
if (ret == SDL_MUTEX_TIMEDOUT) {
return false;
} else if (ret == 0) {
return true;
} else {
// some nasty error
return false;
}
}
}
bool Semaphore::tryWait() {
return SDL_SemTryWait(semaphore) ? false : true;
}
Conditional::Conditional() {
cond = SDL_CreateCond();
}
Conditional::~Conditional() {
SDL_DestroyCond(cond);
}
void Conditional::signal() {
SDL_CondSignal(cond);
}
void Conditional::broadcast() {
SDL_CondBroadcast(cond);
}
bool Conditional::wait(Mutex* mutex, int timeout) {
if (timeout < 0) {
if (SDL_CondWait(cond, mutex->mutex)) {
// error
return false;
} else {
return true;
}
} else {
int ret = SDL_CondWaitTimeout(cond, mutex->mutex, timeout);
if (ret == SDL_MUTEX_TIMEDOUT) {
return false;
} else if (ret == 0) {
return true;
} else {
// some bad error
return false;
}
}
}
} // namespace thread
} // namespace love
+104
View File
@@ -0,0 +1,104 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_PLATFORM_SDL_THREADS_H_
#define LOVE_PLATFORM_SDL_THREADS_H_
#include "SDL.h"
namespace love
{
namespace thread
{
class Mutex {
private:
SDL_mutex* mutex;
Mutex(const Mutex& mutex) {}
friend class Conditional;
public:
Mutex();
~Mutex();
void lock();
void unlock();
};
class ThreadBase {
private:
SDL_Thread* thread;
ThreadBase(ThreadBase& thread) {}
bool running;
static int thread_runner(void* param);
protected:
virtual void main() = 0;
public:
ThreadBase();
virtual ~ThreadBase();
bool start();
void wait();
void kill(); // FIXME: not supported by SDL (SDL's kill is probably cancel)?
static unsigned int threadId();
};
class Semaphore {
private:
Semaphore(const Semaphore& sem) {}
SDL_sem* semaphore;
public:
Semaphore(unsigned int initial_value);
~Semaphore();
unsigned int value();
void post();
bool wait(int timeout = -1);
bool tryWait();
};
// Should conditional inherit from mutex?
class Conditional {
private:
SDL_cond* cond;
public:
Conditional();
~Conditional();
void signal();
void broadcast();
bool wait(Mutex* mutex, int timeout=-1);
};
} // namespace thread
} // namespace love
#endif // !LOVE_PLATFORM_SDL_THREADS_H_
-393
View File
@@ -1,393 +0,0 @@
/**
* Copyright (c) 2006-2010 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_Thread.h"
// anonymous namespace for getting an std::string from the stack
// that may contain embedded NULLs
namespace
{
std::string luax_checklstring(lua_State *L, int idx)
{
size_t len;
const char* str = luaL_checklstring(L, idx, &len);
return std::string(str, len);
}
}
namespace love
{
namespace thread
{
namespace sdl
{
Thread *luax_checkthread(lua_State *L, int idx)
{
return luax_checktype<Thread>(L, idx, "Thread", THREAD_THREAD_T);
}
int w_Thread_start(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
t->start();
return 0;
}
int w_Thread_kill(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
t->kill();
return 0;
}
int w_Thread_wait(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
t->wait();
return 0;
}
int w_Thread_getName(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
// allow names containing \0
lua_pushlstring(L, t->getName().c_str(), t->getName().length());
return 1;
}
int w_Thread_get(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
std::string name = luax_checklstring(L, 2);
t->lock();
ThreadVariant *v = t->get(name);
t->clear(name);
t->unlock();
if (!v)
{
lua_pushnil(L);
return 1;
}
switch(v->type)
{
case BOOLEAN:
lua_pushboolean(L, v->data.boolean);
break;
case NUMBER:
lua_pushnumber(L, v->data.number);
break;
case STRING:
lua_pushlstring(L, v->data.string.str, v->data.string.len);
break;
case LUSERDATA:
lua_pushlightuserdata(L, v->data.userdata);
break;
case FUSERDATA:
{
const char *name = NULL;
love::types.find(v->udatatype, name);
((love::Object *) v->data.userdata)->retain();
luax_newtype(L, name, v->flags, v->data.userdata);
break;
}
default:
lua_pushnil(L);
break;
}
t->lock();
v->release();
t->unlock();
return 1;
}
int w_Thread_demand(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
std::string name = luax_checklstring(L, 2);
t->lock();
ThreadVariant *v = t->demand(name);
t->clear(name);
t->unlock();
if (!v)
{
lua_pushnil(L);
return 1;
}
switch(v->type)
{
case BOOLEAN:
lua_pushboolean(L, v->data.boolean);
break;
case NUMBER:
lua_pushnumber(L, v->data.number);
break;
case STRING:
lua_pushlstring(L, v->data.string.str, v->data.string.len);
break;
case LUSERDATA:
lua_pushlightuserdata(L, v->data.userdata);
break;
case FUSERDATA:
{
const char *name = NULL;
types.find(v->udatatype, name);
((love::Object *) v->data.userdata)->retain();
luax_newtype(L, name, v->flags, v->data.userdata);
break;
}
default:
lua_pushnil(L);
break;
}
t->lock();
v->release();
t->unlock();
return 1;
}
int w_Thread_peek(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
std::string name = luax_checklstring(L, 2);
t->lock();
ThreadVariant *v = t->get(name);
t->unlock();
if (!v)
{
lua_pushnil(L);
return 1;
}
switch(v->type)
{
case BOOLEAN:
lua_pushboolean(L, v->data.boolean);
break;
case NUMBER:
lua_pushnumber(L, v->data.number);
break;
case STRING:
lua_pushlstring(L, v->data.string.str, v->data.string.len);
break;
case LUSERDATA:
lua_pushlightuserdata(L, v->data.userdata);
break;
case FUSERDATA:
{
const char *name = NULL;
types.find(v->udatatype, name);
((love::Object *) v->data.userdata)->retain();
luax_newtype(L, name, v->flags, v->data.userdata);
break;
}
default:
lua_pushnil(L);
break;
}
t->lock();
v->release();
t->unlock();
return 1;
}
Type extractudatatype(lua_State * L, int idx)
{
Type t = INVALID_ID;
if (!lua_isuserdata(L, idx))
return t;
if (luaL_getmetafield (L, idx, "__tostring") == 0)
return t;
lua_pushvalue(L, idx);
int result = lua_pcall(L, 1, 1, 0);
if (result == 0)
types.find(lua_tostring(L, -1), t);
if (result == 0 || result == LUA_ERRRUN)
lua_pop(L, 1);
return t;
}
int w_Thread_set(lua_State *L)
{
Thread *t = luax_checkthread(L, 1);
std::string name = luax_checklstring(L, 2);
ThreadVariant *v;
if (lua_isboolean(L, 3))
{
v = new ThreadVariant(luax_toboolean(L, 3));
}
else if (lua_isnumber(L, 3))
{
v = new ThreadVariant(lua_tonumber(L, 3));
}
else if (lua_isstring(L, 3))
{
size_t len;
const char *str = lua_tolstring(L, 3, &len);
v = new ThreadVariant(str, len);
}
else if (lua_islightuserdata(L, 3))
{
v = new ThreadVariant(lua_touserdata(L, 3));
}
else if (lua_isuserdata(L, 3))
{
v = new ThreadVariant(extractudatatype(L, 3), lua_touserdata(L, 3));
}
else
{
return luaL_error(L, "Expected boolean, number, string or userdata");
}
t->set(name, v);
v->release();
return 0;
}
static const luaL_Reg type_functions[] = {
{ "start", w_Thread_start },
{ "kill", w_Thread_kill },
{ "wait", w_Thread_wait },
{ "getName", w_Thread_getName },
{ "get", w_Thread_get },
{ "demand", w_Thread_demand },
{ "peek", w_Thread_peek },
{ "set", w_Thread_set },
{ 0, 0 }
};
int luaopen_thread(lua_State *L)
{
return luax_register_type(L, "Thread", type_functions);
}
static ThreadModule *instance;
int w_newThread(lua_State *L)
{
std::string name = luax_checklstring(L, 1);
love::Data *data;
if (lua_isstring(L, 2))
luax_convobj(L, 2, "filesystem", "newFile");
if (luax_istype(L, 2, FILESYSTEM_FILE_T))
{
try {
data = luax_checktype<love::filesystem::File>(L, 2, "File", FILESYSTEM_FILE_T)->read();
} catch (love::Exception & e) {
return luaL_error(L, e.what());
}
}
else
data = luax_checktype<love::Data>(L, 2, "Data", DATA_T);
Thread *t = instance->newThread(name, data);
if (!t)
return luaL_error(L, "A thread with that name already exists.");
luax_newtype(L, "Thread", THREAD_THREAD_T, (void*)t);
return 1;
}
int w_getThreads(lua_State *L)
{
unsigned count = instance->getThreadCount();
Thread **list = new Thread*[count];
instance->getThreads(list);
lua_newtable(L);
for (unsigned int i = 0; i<count; i++)
{
// allow names containing \0
lua_pushlstring(L, list[i]->getName().c_str(), list[i]->getName().length());
luax_newtype(L, "Thread", THREAD_THREAD_T, (void*) list[i]);
list[i]->lock();
list[i]->retain();
list[i]->unlock();
lua_settable(L, -3);
}
delete[] list;
return 1;
}
int w_getThread(lua_State *L)
{
if (lua_isnoneornil(L, 1))
{
lua_getglobal(L, "love");
lua_getfield(L, -1, "_curthread");
return 1;
}
std::string name = luax_checklstring(L, 1);
Thread *t = instance->getThread(name);
if (t)
{
luax_newtype(L, "Thread", THREAD_THREAD_T, (void*)t);
t->lock();
t->retain();
t->unlock();
}
else
lua_pushnil(L);
return 1;
}
// List of functions to wrap.
static const luaL_Reg module_functions[] = {
{ "newThread", w_newThread },
{ "getThread", w_getThread },
{ "getThreads", w_getThreads },
{ 0, 0 }
};
static const lua_CFunction types[] = {
luaopen_thread,
0
};
int luaopen_love_thread(lua_State *L)
{
if(instance == 0)
{
try
{
instance = new ThreadModule();
lua_getglobal(L, "love");
Thread *curthread = instance->getThread("main");
curthread->lock();
curthread->retain();
curthread->unlock();
luax_newtype(L, "Thread", THREAD_THREAD_T, (void*)curthread);
lua_setfield(L, -2, "_curthread");
}
catch(Exception & e)
{
return luaL_error(L, e.what());
}
}
else
instance->retain();
WrappedModule w;
w.module = instance;
w.name = "thread";
w.flags = MODULE_T;
w.functions = module_functions;
w.types = types;
return luax_register_module(L, w);
}
}
}
}
-56
View File
@@ -1,56 +0,0 @@
/**
* Copyright (c) 2006-2011 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_THREAD_SDL_WRAP_THREAD_H
#define LOVE_THREAD_SDL_WRAP_THREAD_H
// LOVE
#include <common/config.h>
#include "Thread.h"
namespace love
{
extern StringMap<Type, TYPE_MAX_ENUM> types;
namespace thread
{
namespace sdl
{
Thread *luax_checkthread(lua_State *L, int idx);
int w_Thread_start(lua_State *L);
int w_Thread_kill(lua_State *L);
int w_Thread_wait(lua_State *L);
int w_Thread_getName(lua_State *L);
int w_Thread_get(lua_State *L);
int w_Thread_demand(lua_State *L);
int w_Thread_peek(lua_State *L);
int w_Thread_set(lua_State *L);
int luaopen_thread(lua_State *L);
int w_newThread(lua_State *L);
int w_getThreads(lua_State *L);
int w_getThread(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_thread(lua_State * L);
} // sdl
} // thread
} // love
#endif // LOVE_THREAD_SDL_WRAP_THREAD_H