mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Merge in channels from love-experiments
Rewritten love.thread and changed communication method from weird system before, to channels. --HG-- branch : minor
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "sound/Decoder.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
@@ -34,9 +36,16 @@ Audio::PoolThread::PoolThread(Pool *pool)
|
||||
: pool(pool)
|
||||
, finish(false)
|
||||
{
|
||||
mutex = thread::newMutex();
|
||||
}
|
||||
|
||||
void Audio::PoolThread::main()
|
||||
Audio::PoolThread::~PoolThread()
|
||||
{
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
|
||||
void Audio::PoolThread::threadFunction()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -59,7 +68,6 @@ void Audio::PoolThread::setFinish()
|
||||
finish = true;
|
||||
}
|
||||
|
||||
|
||||
Audio::Audio() : distanceModel(DISTANCE_INVERSE_CLAMPED)
|
||||
{
|
||||
// Passing zero for default device.
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
// The Pool.
|
||||
Pool *pool;
|
||||
|
||||
class PoolThread: public thread::ThreadBase
|
||||
class PoolThread: public thread::Threadable
|
||||
{
|
||||
protected:
|
||||
Pool *pool;
|
||||
@@ -120,13 +120,13 @@ private:
|
||||
volatile bool finish;
|
||||
|
||||
// finish lock
|
||||
thread::Mutex mutex;
|
||||
|
||||
virtual void main();
|
||||
thread::Mutex *mutex;
|
||||
|
||||
public:
|
||||
PoolThread(Pool *pool);
|
||||
~PoolThread();
|
||||
void setFinish();
|
||||
void threadFunction();
|
||||
};
|
||||
|
||||
PoolThread *poolThread;
|
||||
|
||||
@@ -35,7 +35,7 @@ Pool::Pool()
|
||||
alGenSources(NUM_SOURCES, sources);
|
||||
|
||||
// Create the mutex.
|
||||
mutex = new thread::Mutex();
|
||||
mutex = thread::newMutex();
|
||||
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
throw love::Exception("Could not generate sources.");
|
||||
|
||||
@@ -80,8 +80,14 @@ Message *Message::fromLua(lua_State *L, int n)
|
||||
return m;
|
||||
}
|
||||
|
||||
Event::Event()
|
||||
{
|
||||
mutex = thread::newMutex();
|
||||
}
|
||||
|
||||
Event::~Event()
|
||||
{
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
void Event::push(Message *msg)
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
class Event : public Module
|
||||
{
|
||||
public:
|
||||
Event();
|
||||
virtual ~Event();
|
||||
|
||||
void push(Message *msg);
|
||||
@@ -68,13 +69,12 @@ public:
|
||||
static bool getConstant(love::keyboard::Keyboard::Key in, const char *&out);
|
||||
|
||||
protected:
|
||||
thread::Mutex mutex;
|
||||
thread::Mutex *mutex;
|
||||
std::queue<Message *> queue;
|
||||
static StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry buttonEntries[];
|
||||
static StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM> buttons;
|
||||
static StringMap<love::keyboard::Keyboard::Key, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
|
||||
static StringMap<love::keyboard::Keyboard::Key, love::keyboard::Keyboard::KEY_MAX_ENUM> keys;
|
||||
|
||||
}; // Event
|
||||
|
||||
} // event
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "ImageData.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using love::thread::Lock;
|
||||
|
||||
namespace love
|
||||
@@ -27,6 +29,16 @@ namespace love
|
||||
namespace image
|
||||
{
|
||||
|
||||
ImageData::ImageData()
|
||||
{
|
||||
mutex = thread::newMutex();
|
||||
}
|
||||
|
||||
ImageData::~ImageData()
|
||||
{
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
void *ImageData::getData() const
|
||||
{
|
||||
return data;
|
||||
|
||||
@@ -59,7 +59,7 @@ protected:
|
||||
// We need to be thread-safe
|
||||
// so we lock when we're accessing our
|
||||
// data
|
||||
Mutex mutex;
|
||||
Mutex *mutex;
|
||||
|
||||
public:
|
||||
|
||||
@@ -73,10 +73,12 @@ public:
|
||||
FORMAT_MAX_ENUM
|
||||
};
|
||||
|
||||
ImageData();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
**/
|
||||
virtual ~ImageData() {};
|
||||
virtual ~ImageData();
|
||||
|
||||
static bool getConstant(const char *in, Format &out);
|
||||
static bool getConstant(Format in, const char *&out);
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
using love::thread::Lock;
|
||||
|
||||
static Mutex devilMutex;
|
||||
static Mutex *devilMutex = 0;
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -96,6 +96,9 @@ void ImageData::create(int width, int height, void *data)
|
||||
|
||||
void ImageData::load(Data *data)
|
||||
{
|
||||
if (!devilMutex)
|
||||
devilMutex = thread::newMutex();
|
||||
|
||||
Lock lock(devilMutex);
|
||||
ILuint image;
|
||||
ilGenImages(1, &image);
|
||||
@@ -132,6 +135,9 @@ void ImageData::load(Data *data)
|
||||
|
||||
void ImageData::encode(love::filesystem::File *f, ImageData::Format format)
|
||||
{
|
||||
if (!devilMutex)
|
||||
devilMutex = thread::newMutex();
|
||||
|
||||
Lock lock1(devilMutex);
|
||||
Lock lock2(mutex);
|
||||
|
||||
|
||||
@@ -57,6 +57,11 @@ public:
|
||||
// Implements ImageData.
|
||||
void encode(love::filesystem::File *f, Format format);
|
||||
|
||||
// We need to be thread-safe
|
||||
// so we lock when we're accessing our
|
||||
// data
|
||||
Mutex *mutex;
|
||||
|
||||
}; // ImageData
|
||||
|
||||
} // devil
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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 "Channel.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
static std::map<std::string, Channel*> namedChannels;
|
||||
static Mutex *namedChannelMutex;
|
||||
Channel *Channel::getChannel(const std::string &name)
|
||||
{
|
||||
if (!namedChannelMutex)
|
||||
namedChannelMutex = newMutex();
|
||||
Lock l(namedChannelMutex);
|
||||
if (!namedChannels.count(name))
|
||||
namedChannels[name] = new Channel(name);
|
||||
else
|
||||
namedChannels[name]->retain();
|
||||
return namedChannels[name];
|
||||
}
|
||||
|
||||
Channel::Channel()
|
||||
: named(false)
|
||||
{
|
||||
mutex = newMutex();
|
||||
cond = newConditional();
|
||||
}
|
||||
|
||||
Channel::Channel(const std::string &name)
|
||||
: named(true), name(name)
|
||||
{
|
||||
mutex = newMutex();
|
||||
cond = newConditional();
|
||||
}
|
||||
|
||||
Channel::~Channel()
|
||||
{
|
||||
while (!queue.empty())
|
||||
{
|
||||
queue.front()->release();
|
||||
queue.pop();
|
||||
}
|
||||
|
||||
delete mutex;
|
||||
delete cond;
|
||||
if (named)
|
||||
{
|
||||
Lock l(namedChannelMutex);
|
||||
namedChannels.erase(name);
|
||||
}
|
||||
}
|
||||
|
||||
void Channel::push(Variant *var)
|
||||
{
|
||||
if (!var)
|
||||
return;
|
||||
Lock l(mutex);
|
||||
var->retain();
|
||||
// Keep a reference to ourselves
|
||||
// if we're non-empty and named.
|
||||
if (named && queue.empty())
|
||||
retain();
|
||||
queue.push(var);
|
||||
cond->signal();
|
||||
}
|
||||
|
||||
Variant *Channel::pop()
|
||||
{
|
||||
Lock l(mutex);
|
||||
if (queue.empty())
|
||||
return 0;
|
||||
|
||||
Variant *var = queue.front();
|
||||
queue.pop();
|
||||
|
||||
// Release our reference to ourselves
|
||||
// if we're empty and named.
|
||||
if (named && queue.empty())
|
||||
release();
|
||||
return var;
|
||||
} // NOTE: Returns a retained Variant
|
||||
|
||||
Variant *Channel::demand()
|
||||
{
|
||||
Variant *var;
|
||||
while (!(var = pop()))
|
||||
{
|
||||
mutex->lock();
|
||||
cond->wait(mutex);
|
||||
mutex->unlock();
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
Variant *Channel::peek()
|
||||
{
|
||||
Lock l(mutex);
|
||||
if (queue.empty())
|
||||
return 0;
|
||||
|
||||
Variant *var = queue.front();
|
||||
var->retain();
|
||||
return var;
|
||||
}
|
||||
|
||||
int Channel::count()
|
||||
{
|
||||
Lock l(mutex);
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
void Channel::clear()
|
||||
{
|
||||
Lock l(mutex);
|
||||
while (!queue.empty())
|
||||
{
|
||||
queue.front()->release();
|
||||
queue.pop();
|
||||
}
|
||||
|
||||
// Once again, release our own
|
||||
// reference if we're named.
|
||||
if (named)
|
||||
release();
|
||||
}
|
||||
} // thread
|
||||
} // love
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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_CHANNEL_H
|
||||
#define LOVE_THREAD_CHANNEL_H
|
||||
|
||||
// STL
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
// LOVE
|
||||
#include <common/Variant.h>
|
||||
#include <thread/threads.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
class Channel : public love::Object
|
||||
{
|
||||
private:
|
||||
Mutex *mutex;
|
||||
Conditional *cond;
|
||||
std::queue<Variant*> queue;
|
||||
bool named;
|
||||
std::string name;
|
||||
Channel(const std::string &name);
|
||||
|
||||
public:
|
||||
Channel();
|
||||
~Channel();
|
||||
static Channel *getChannel(const std::string &name);
|
||||
|
||||
void push(Variant *var);
|
||||
Variant *pop();
|
||||
Variant *demand();
|
||||
Variant *peek();
|
||||
int count();
|
||||
void clear();
|
||||
}; // Channel
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_CHANNEL_H
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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 "LuaThread.h"
|
||||
#include <common/config.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
|
||||
{
|
||||
LuaThread::LuaThread(const std::string &name, love::Data *code)
|
||||
: name(name), code(code)
|
||||
{
|
||||
code->retain();
|
||||
}
|
||||
|
||||
LuaThread::~LuaThread()
|
||||
{
|
||||
code->release();
|
||||
}
|
||||
|
||||
void LuaThread::threadFunction()
|
||||
{
|
||||
this->retain();
|
||||
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);
|
||||
if (luaL_loadbuffer(L, (const char*) code->getData(), code->getSize(), name.c_str()) != 0)
|
||||
error = luax_tostring(L, -1);
|
||||
else
|
||||
if (lua_pcall(L, 0, 0, 0) != 0)
|
||||
error = luax_tostring(L, -1);
|
||||
lua_close(L);
|
||||
this->release();
|
||||
}
|
||||
|
||||
const std::string &LuaThread::getError()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
} // thread
|
||||
} // love
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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_LUATHREAD_H
|
||||
#define LOVE_THREAD_LUATHREAD_H
|
||||
|
||||
// STL
|
||||
#include <string>
|
||||
|
||||
// LOVE
|
||||
#include <common/Object.h>
|
||||
#include <common/Data.h>
|
||||
#include <thread/threads.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
class LuaThread : public love::Object, public Threadable
|
||||
{
|
||||
private:
|
||||
love::Data *code;
|
||||
std::string name;
|
||||
std::string error;
|
||||
|
||||
public:
|
||||
LuaThread(const std::string &name, love::Data *code);
|
||||
~LuaThread();
|
||||
void threadFunction();
|
||||
const std::string &getError();
|
||||
};
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_LUATHREAD_H
|
||||
@@ -1,317 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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
|
||||
{
|
||||
|
||||
Thread::ThreadThread::ThreadThread(ThreadData *comm)
|
||||
: comm(comm)
|
||||
{
|
||||
}
|
||||
|
||||
void Thread::ThreadThread::main()
|
||||
{
|
||||
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)
|
||||
{
|
||||
{
|
||||
Lock lock((Mutex *) comm->mutex);
|
||||
Variant *v = new Variant(lua_tostring(L, -1), lua_strlen(L, -1));
|
||||
comm->setValue("error", v);
|
||||
v->release();
|
||||
}
|
||||
((Conditional *) comm->cond)->broadcast();
|
||||
}
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Variant *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, Variant *v)
|
||||
{
|
||||
if (shared.count(name) != 0)
|
||||
shared[name]->release();
|
||||
v->retain();
|
||||
shared[name] = v;
|
||||
}
|
||||
|
||||
std::vector<std::string> ThreadData::getKeys()
|
||||
{
|
||||
std::vector<std::string> keys;
|
||||
for (std::map<std::string, Variant *>::iterator it = shared.begin(); it != shared.end(); it++)
|
||||
{
|
||||
keys.push_back(it->first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
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 = new Mutex();
|
||||
cond = new Conditional();
|
||||
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 = new Mutex();
|
||||
cond = new Conditional();
|
||||
comm = new ThreadData(name.c_str(), name.length(), NULL, mutex, cond);
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
if (data)
|
||||
delete[] data;
|
||||
delete comm;
|
||||
module->unregister(name);
|
||||
delete mutex;
|
||||
delete cond;
|
||||
module->release();
|
||||
}
|
||||
|
||||
void Thread::start()
|
||||
{
|
||||
if (!handle && isThread)
|
||||
{
|
||||
handle = new ThreadThread(comm);
|
||||
handle->start();
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::kill()
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
Lock lock((Mutex *) _gcmutex);
|
||||
handle->kill();
|
||||
delete handle;
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::wait()
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
handle->wait();
|
||||
delete handle;
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::lock()
|
||||
{
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
void Thread::unlock()
|
||||
{
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
std::string Thread::getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
Variant *Thread::get(const std::string &name)
|
||||
{
|
||||
Variant *v = comm->getValue(name);
|
||||
if (v)
|
||||
v->retain();
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::string> Thread::getKeys()
|
||||
{
|
||||
return comm->getKeys();
|
||||
}
|
||||
|
||||
Variant *Thread::demand(const std::string &name)
|
||||
{
|
||||
Variant *v = comm->getValue(name);
|
||||
while (!v)
|
||||
{
|
||||
if (comm->getValue("error"))
|
||||
return 0;
|
||||
cond->wait(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, Variant *v)
|
||||
{
|
||||
lock(); //this function explicitly locks
|
||||
comm->setValue(name, v); //because we need
|
||||
unlock(); //it to unlock here for the cond
|
||||
cond->broadcast();
|
||||
}
|
||||
|
||||
ThreadModule::ThreadModule()
|
||||
{
|
||||
threads["main"] = new Thread(this, "main");
|
||||
}
|
||||
|
||||
ThreadModule::~ThreadModule()
|
||||
{
|
||||
for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++)
|
||||
{
|
||||
i->second->kill();
|
||||
delete i->second;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
// FIXME: shouldn't the thread be deleted?
|
||||
threads.erase(i);
|
||||
}
|
||||
|
||||
const char *ThreadModule::getName() const
|
||||
{
|
||||
return "love.thread.sdl";
|
||||
}
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
+11
-91
@@ -18,108 +18,28 @@
|
||||
* 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
|
||||
|
||||
// STL
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#ifndef LOVE_THREAD_THREAD_H
|
||||
#define LOVE_THREAD_THREAD_H
|
||||
|
||||
// LOVE
|
||||
#include "filesystem/File.h"
|
||||
#include "common/runtime.h"
|
||||
#include "common/Module.h"
|
||||
#include "common/Variant.h"
|
||||
#include "thread/threads.h"
|
||||
#include <common/runtime.h>
|
||||
#include <common/Object.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
class ThreadModule;
|
||||
|
||||
class ThreadData
|
||||
class Thread
|
||||
{
|
||||
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);
|
||||
Variant *getValue(const std::string &name);
|
||||
void clearValue(const std::string &name);
|
||||
void setValue(const std::string &name, Variant *v);
|
||||
std::vector<std::string> getKeys();
|
||||
virtual ~Thread() {}
|
||||
virtual bool start() = 0;
|
||||
virtual void wait() = 0;
|
||||
virtual void kill() = 0;
|
||||
}; // ThreadObject
|
||||
|
||||
void *mutex;
|
||||
void *cond;
|
||||
private:
|
||||
char *code;
|
||||
char *name;
|
||||
std::map<std::string, Variant *> shared;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
class Thread : public love::Object
|
||||
{
|
||||
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();
|
||||
Variant *get(const std::string &name);
|
||||
std::vector<std::string> getKeys();
|
||||
Variant *demand(const std::string &name);
|
||||
void clear(const std::string &name);
|
||||
void set(const std::string &name, Variant *v);
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
class ThreadThread: public ThreadBase
|
||||
{
|
||||
private:
|
||||
ThreadData *comm;
|
||||
|
||||
protected:
|
||||
virtual void main();
|
||||
|
||||
public:
|
||||
ThreadThread(ThreadData *comm);
|
||||
};
|
||||
|
||||
ThreadThread *handle;
|
||||
|
||||
ThreadModule *module;
|
||||
ThreadData *comm;
|
||||
std::string name;
|
||||
char *data;
|
||||
Mutex *mutex;
|
||||
Conditional *cond;
|
||||
bool isThread;
|
||||
}; // Thread
|
||||
|
||||
typedef std::map<std::string, Thread *> threadlist_t;
|
||||
|
||||
class ThreadModule : public love::Module
|
||||
{
|
||||
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;
|
||||
private:
|
||||
threadlist_t threads;
|
||||
}; // ThreadModule
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_SDL_THREAD_H
|
||||
#endif // LOVE_THREAD_THREAD_H
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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 "ThreadModule.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
const char *ThreadModule::getName() const
|
||||
{
|
||||
return "love.thread.sdl";
|
||||
}
|
||||
|
||||
LuaThread *ThreadModule::newThread(const std::string &name, love::Data *data)
|
||||
{
|
||||
LuaThread *lt = new LuaThread(name, data);
|
||||
return lt;
|
||||
}
|
||||
|
||||
Channel *ThreadModule::newChannel()
|
||||
{
|
||||
return new Channel();
|
||||
}
|
||||
|
||||
Channel *ThreadModule::getChannel(const std::string &name)
|
||||
{
|
||||
return Channel::getChannel(name);
|
||||
}
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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_THREADMODULE_H
|
||||
#define LOVE_THREAD_THREADMODULE_H
|
||||
|
||||
// STL
|
||||
#include <string>
|
||||
|
||||
// LOVE
|
||||
#include <common/Data.h>
|
||||
#include <common/Module.h>
|
||||
#include <thread/Thread.h>
|
||||
#include <thread/Channel.h>
|
||||
#include <thread/LuaThread.h>
|
||||
#include <thread/threads.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
class ThreadModule : public love::Module
|
||||
{
|
||||
public:
|
||||
virtual ~ThreadModule() {}
|
||||
LuaThread *newThread(const std::string &name, love::Data *data);
|
||||
Channel *newChannel();
|
||||
Channel *getChannel(const std::string &name);
|
||||
|
||||
const char *getName() const;
|
||||
}; // ThreadModule
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_THREADMODULE_H
|
||||
@@ -1,192 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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"
|
||||
#ifdef LOVE_MACOSX
|
||||
#include "common/delay.h" // for Mac OS X's fake sem_timedwait
|
||||
#endif
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
Mutex::Mutex()
|
||||
{
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
}
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
pthread_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
void Mutex::lock()
|
||||
{
|
||||
pthread_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
void Mutex::unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void *ThreadBase::thread_runner(void *param)
|
||||
{
|
||||
ThreadBase *thread = (ThreadBase *)param;
|
||||
thread->main();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ThreadBase::ThreadBase()
|
||||
: running(false)
|
||||
{
|
||||
pthread_t thread;
|
||||
}
|
||||
|
||||
ThreadBase::~ThreadBase()
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
bool ThreadBase::start()
|
||||
{
|
||||
if (pthread_create(&thread, NULL, thread_runner, this))
|
||||
return false;
|
||||
return (running = true);
|
||||
}
|
||||
|
||||
void ThreadBase::wait()
|
||||
{
|
||||
pthread_join(thread, NULL);
|
||||
running = false;
|
||||
}
|
||||
|
||||
void ThreadBase::kill()
|
||||
{
|
||||
pthread_kill(thread, 9);
|
||||
running = false;
|
||||
}
|
||||
|
||||
unsigned int ThreadBase::threadId()
|
||||
{
|
||||
return (unsigned int)((size_t)pthread_self());
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(unsigned int initial_value)
|
||||
{
|
||||
sem_init(&sem, 0, initial_value);
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
sem_destroy(&sem);
|
||||
}
|
||||
|
||||
unsigned int Semaphore::value()
|
||||
{
|
||||
int val = 0;
|
||||
if (sem_getvalue(&sem, &val))
|
||||
return 0;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
void Semaphore::post()
|
||||
{
|
||||
sem_post(&sem);
|
||||
}
|
||||
|
||||
bool Semaphore::wait(int timeout)
|
||||
{
|
||||
if (timeout < 0)
|
||||
return !sem_wait(&sem);
|
||||
else if (timeout == 0)
|
||||
return !sem_trywait(&sem);
|
||||
else
|
||||
{
|
||||
#ifdef LOVE_MACOSX
|
||||
// OS X lacks sem_timedwait, so we fake it with a busy loop
|
||||
time_t timer = time(NULL)*1000 + timeout;
|
||||
int retval = 0;
|
||||
do
|
||||
{
|
||||
retval = sem_trywait(&sem);
|
||||
if (retval == 0) break;
|
||||
delay(1);
|
||||
}
|
||||
while (time(NULL)*1000 < timer);
|
||||
return !retval;
|
||||
#else
|
||||
struct timespec ts;
|
||||
ts.tv_sec = timeout/1000;
|
||||
ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||
return !sem_timedwait(&sem, &ts);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool Semaphore::tryWait()
|
||||
{
|
||||
return !sem_trywait(&sem);
|
||||
}
|
||||
|
||||
Conditional::Conditional()
|
||||
{
|
||||
pthread_cond_init(&cond, NULL);
|
||||
}
|
||||
|
||||
Conditional::~Conditional()
|
||||
{
|
||||
pthread_cond_destroy(&cond);
|
||||
}
|
||||
|
||||
void Conditional::signal()
|
||||
{
|
||||
pthread_cond_signal(&cond);
|
||||
}
|
||||
|
||||
void Conditional::broadcast()
|
||||
{
|
||||
pthread_cond_broadcast(&cond);
|
||||
}
|
||||
|
||||
bool Conditional::wait(Mutex *mutex, int timeout)
|
||||
{
|
||||
if (timeout < 0)
|
||||
return !pthread_cond_wait(&cond, &mutex->mutex);
|
||||
else
|
||||
{
|
||||
struct timespec ts;
|
||||
int ret;
|
||||
|
||||
ts.tv_sec = timeout / 1000;
|
||||
ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||
|
||||
ret = pthread_cond_timedwait(&cond, &mutex->mutex, &ts);
|
||||
return (ret == 0);
|
||||
}
|
||||
}
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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_POSIX_THREADS_H
|
||||
#define LOVE_THREAD_POSIX_THREADS_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex;
|
||||
Mutex(const Mutex &mutex) {}
|
||||
|
||||
friend class Conditional;
|
||||
};
|
||||
|
||||
|
||||
class ThreadBase
|
||||
{
|
||||
public:
|
||||
ThreadBase();
|
||||
virtual ~ThreadBase();
|
||||
|
||||
bool start();
|
||||
void wait();
|
||||
void kill();
|
||||
|
||||
static unsigned int threadId();
|
||||
|
||||
protected:
|
||||
virtual void main() = 0;
|
||||
|
||||
private:
|
||||
pthread_t thread;
|
||||
ThreadBase(ThreadBase &thread) {}
|
||||
|
||||
static void *thread_runner(void *param);
|
||||
bool running;
|
||||
};
|
||||
|
||||
class Semaphore
|
||||
{
|
||||
public:
|
||||
Semaphore(unsigned int initial_value);
|
||||
~Semaphore();
|
||||
|
||||
unsigned int value();
|
||||
void post();
|
||||
bool wait(int timeout = -1);
|
||||
bool tryWait();
|
||||
|
||||
private:
|
||||
Semaphore(const Semaphore &sem) {}
|
||||
sem_t sem;
|
||||
};
|
||||
|
||||
// Should conditional inherit from mutex?
|
||||
class Conditional
|
||||
{
|
||||
public:
|
||||
Conditional();
|
||||
~Conditional();
|
||||
|
||||
void signal();
|
||||
void broadcast();
|
||||
bool wait(Mutex *mutex, int timeout=-1);
|
||||
|
||||
private:
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
|
||||
#endif // LOVE_THREAD_POSIX_THREADS_H
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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 "Thread.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
Thread::Thread(Threadable *t)
|
||||
: t(t), running(false), thread(0)
|
||||
{
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
if (!running) // Clean up handle
|
||||
wait();
|
||||
/*
|
||||
if (running)
|
||||
wait();
|
||||
FIXME: Needed for proper thread cleanup
|
||||
*/
|
||||
}
|
||||
|
||||
bool Thread::start()
|
||||
{
|
||||
Lock l(mutex);
|
||||
if (running)
|
||||
return false;
|
||||
if (thread) // Clean old handle up
|
||||
SDL_WaitThread(thread, 0);
|
||||
thread = SDL_CreateThread(thread_runner, this);
|
||||
running = (thread != 0);
|
||||
return running;
|
||||
}
|
||||
|
||||
void Thread::wait()
|
||||
{
|
||||
mutex.lock();
|
||||
if (!thread)
|
||||
return;
|
||||
mutex.unlock();
|
||||
SDL_WaitThread(thread, 0);
|
||||
Lock l(mutex);
|
||||
running = false;
|
||||
thread = 0;
|
||||
}
|
||||
|
||||
void Thread::kill()
|
||||
{
|
||||
Lock l(mutex);
|
||||
if (!running)
|
||||
return;
|
||||
SDL_KillThread(thread);
|
||||
SDL_WaitThread(thread, 0);
|
||||
running = false;
|
||||
thread = 0;
|
||||
}
|
||||
|
||||
int Thread::thread_runner(void *data)
|
||||
{
|
||||
Thread *self = (Thread*) data; // some compilers don't like 'this'
|
||||
self->t->threadFunction();
|
||||
Lock l(self->mutex);
|
||||
self->running = false;
|
||||
return 0;
|
||||
}
|
||||
} // sdl
|
||||
} // thread
|
||||
} // love
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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
|
||||
|
||||
// LOVE
|
||||
#include <thread/Thread.h>
|
||||
#include "threads.h"
|
||||
|
||||
// SDL
|
||||
#include <SDL_thread.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
class Thread : public thread::Thread
|
||||
{
|
||||
private:
|
||||
Threadable *t;
|
||||
bool running;
|
||||
SDL_Thread *thread;
|
||||
static int thread_runner(void *data);
|
||||
Mutex mutex;
|
||||
|
||||
public:
|
||||
Thread(Threadable *t);
|
||||
~Thread();
|
||||
bool start();
|
||||
void kill();
|
||||
void wait();
|
||||
}; // Thread
|
||||
} // sdl
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_SDL_THREAD_H
|
||||
@@ -19,12 +19,14 @@
|
||||
**/
|
||||
|
||||
#include "threads.h"
|
||||
#include "Thread.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
namespace sdl
|
||||
{
|
||||
Mutex::Mutex()
|
||||
{
|
||||
mutex = SDL_CreateMutex();
|
||||
@@ -45,90 +47,6 @@ void Mutex::unlock()
|
||||
SDL_mutexV(mutex);
|
||||
}
|
||||
|
||||
int ThreadBase::thread_runner(void *param)
|
||||
{
|
||||
ThreadBase *thread = (ThreadBase *)param;
|
||||
thread->main();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadBase::ThreadBase()
|
||||
: running(false)
|
||||
{
|
||||
}
|
||||
|
||||
ThreadBase::~ThreadBase()
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
bool ThreadBase::start()
|
||||
{
|
||||
thread = SDL_CreateThread(thread_runner, this);
|
||||
if (thread == NULL)
|
||||
return false;
|
||||
else
|
||||
return (running = 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);
|
||||
return (ret == 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool Semaphore::tryWait()
|
||||
{
|
||||
return SDL_SemTryWait(semaphore) ? false : true;
|
||||
}
|
||||
|
||||
Conditional::Conditional()
|
||||
{
|
||||
cond = SDL_CreateCond();
|
||||
@@ -149,13 +67,34 @@ void Conditional::broadcast()
|
||||
SDL_CondBroadcast(cond);
|
||||
}
|
||||
|
||||
bool Conditional::wait(Mutex *mutex, int timeout)
|
||||
bool Conditional::wait(thread::Mutex *_mutex, int timeout)
|
||||
{
|
||||
// Yes, I realise this can be dangerous,
|
||||
// however, you're asking for it if you're
|
||||
// mixing thread implementations.
|
||||
Mutex *mutex = (Mutex*) _mutex;
|
||||
if (timeout < 0)
|
||||
return !SDL_CondWait(cond, mutex->mutex);
|
||||
else
|
||||
return (SDL_CondWaitTimeout(cond, mutex->mutex, timeout) == 0);
|
||||
}
|
||||
|
||||
} // sdl
|
||||
|
||||
thread::Mutex *newMutex()
|
||||
{
|
||||
return new sdl::Mutex();
|
||||
}
|
||||
|
||||
thread::Conditional *newConditional()
|
||||
{
|
||||
return new sdl::Conditional();
|
||||
}
|
||||
|
||||
thread::Thread *newThread(Threadable *t)
|
||||
{
|
||||
return new sdl::Thread(t);
|
||||
}
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
@@ -21,87 +21,51 @@
|
||||
#ifndef LOVE_THREAD_SDL_THREADS_H
|
||||
#define LOVE_THREAD_SDL_THREADS_H
|
||||
|
||||
#include "SDL.h"
|
||||
#include "common/config.h"
|
||||
#include <common/config.h>
|
||||
#include <thread/threads.h>
|
||||
|
||||
#include <SDL_thread.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
class Mutex
|
||||
namespace sdl
|
||||
{
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
class Conditional;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
SDL_mutex *mutex;
|
||||
Mutex(const Mutex &/* mutex*/) {}
|
||||
class Mutex : public thread::Mutex
|
||||
{
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
friend class Conditional;
|
||||
};
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
SDL_mutex* mutex;
|
||||
Mutex(const Mutex&/* mutex*/) {}
|
||||
|
||||
friend class Conditional;
|
||||
};
|
||||
|
||||
class ThreadBase
|
||||
{
|
||||
public:
|
||||
ThreadBase();
|
||||
virtual ~ThreadBase();
|
||||
class Conditional : public thread::Conditional
|
||||
{
|
||||
public:
|
||||
Conditional();
|
||||
~Conditional();
|
||||
|
||||
bool start();
|
||||
void wait();
|
||||
void kill(); // FIXME: not supported by SDL (SDL's kill is probably cancel)?
|
||||
void signal();
|
||||
void broadcast();
|
||||
bool wait(thread::Mutex* mutex, int timeout=-1);
|
||||
|
||||
static unsigned int threadId();
|
||||
|
||||
protected:
|
||||
virtual void main() = 0;
|
||||
|
||||
private:
|
||||
SDL_Thread *thread;
|
||||
ThreadBase(ThreadBase &/* thread*/) {}
|
||||
bool running;
|
||||
|
||||
static int thread_runner(void *param);
|
||||
};
|
||||
|
||||
class Semaphore
|
||||
{
|
||||
public:
|
||||
Semaphore(unsigned int initial_value);
|
||||
~Semaphore();
|
||||
|
||||
unsigned int value();
|
||||
void post();
|
||||
bool wait(int timeout = -1);
|
||||
bool tryWait();
|
||||
|
||||
private:
|
||||
Semaphore(const Semaphore &/* sem*/) {}
|
||||
SDL_sem *semaphore;
|
||||
};
|
||||
|
||||
// Should conditional inherit from mutex?
|
||||
class Conditional
|
||||
{
|
||||
public:
|
||||
Conditional();
|
||||
~Conditional();
|
||||
|
||||
void signal();
|
||||
void broadcast();
|
||||
bool wait(Mutex *mutex, int timeout=-1);
|
||||
|
||||
private:
|
||||
SDL_cond *cond;
|
||||
};
|
||||
private:
|
||||
SDL_cond* cond;
|
||||
};
|
||||
|
||||
} // sdl
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
|
||||
#endif // LOVE_THREAD_SDL_THREADS_H
|
||||
#endif /* LOVE_THREAD_SDL_THREADS_H */
|
||||
|
||||
@@ -20,28 +20,51 @@
|
||||
|
||||
#include "threads.h"
|
||||
|
||||
#if LOVE_THREADS == LOVE_THREADS_POSIX
|
||||
# include "posix/threads.cpp"
|
||||
#elif LOVE_THREADS == LOVE_THREADS_WIN32
|
||||
# include "win32/threads.cpp"
|
||||
#elif LOVE_THREADS == LOVE_THREADS_SDL
|
||||
# include "sdl/threads.cpp"
|
||||
#endif
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
const char *threadAPI()
|
||||
Lock::Lock(Mutex *m)
|
||||
: mutex(m)
|
||||
{
|
||||
#if LOVE_THREADS == LOVE_THREADS_POSIX
|
||||
return "posix";
|
||||
#elif LOVE_THREADS == LOVE_THREADS_WIN32
|
||||
return "win32";
|
||||
#elif LOVE_THREADS == LOVE_THREADS_SDL
|
||||
return "sdl";
|
||||
#endif
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
Lock::Lock(Mutex &m)
|
||||
: mutex(&m)
|
||||
{
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
Lock::~Lock()
|
||||
{
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
Threadable::Threadable()
|
||||
{
|
||||
owner = newThread(this);
|
||||
}
|
||||
|
||||
Threadable::~Threadable()
|
||||
{
|
||||
delete owner;
|
||||
}
|
||||
|
||||
bool Threadable::start()
|
||||
{
|
||||
return owner->start();
|
||||
}
|
||||
|
||||
void Threadable::wait()
|
||||
{
|
||||
owner->wait();
|
||||
}
|
||||
|
||||
void Threadable::kill()
|
||||
{
|
||||
owner->kill();
|
||||
}
|
||||
|
||||
} // thread
|
||||
|
||||
@@ -21,66 +21,64 @@
|
||||
#ifndef LOVE_THREAD_THREADS_H
|
||||
#define LOVE_THREAD_THREADS_H
|
||||
|
||||
#include "common/config.h"
|
||||
|
||||
#define LOVE_THREADS_SDL 0
|
||||
#define LOVE_THREADS_WIN32 1
|
||||
#define LOVE_THREADS_POSIX 2
|
||||
|
||||
// Choose correct threads API.
|
||||
// Headless love uses either windows threads or posix threads.
|
||||
// Headed (standard) love uses SDL threads.
|
||||
#ifdef LOVE_HEADLESS
|
||||
# ifdef WIN32
|
||||
# define LOVE_THREADS LOVE_THREADS_WIN32
|
||||
# else
|
||||
# define LOVE_THREADS LOVE_THREADS_POSIX
|
||||
# endif
|
||||
#else
|
||||
# define LOVE_THREADS LOVE_THREADS_SDL
|
||||
#endif
|
||||
|
||||
|
||||
// include the correct header
|
||||
#if LOVE_THREADS == LOVE_THREADS_POSIX
|
||||
# include "posix/threads.h"
|
||||
#elif LOVE_THREADS == LOVE_THREADS_WIN32
|
||||
# include "win32/threads.h"
|
||||
#elif LOVE_THREADS == LOVE_THREADS_SDL
|
||||
# include "sdl/threads.h"
|
||||
#endif
|
||||
|
||||
#include <common/config.h>
|
||||
#include "Thread.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
const char *threadAPI();
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
virtual ~Mutex() {}
|
||||
|
||||
virtual void lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
};
|
||||
|
||||
class Conditional
|
||||
{
|
||||
public:
|
||||
virtual ~Conditional() {}
|
||||
|
||||
virtual void signal() = 0;
|
||||
virtual void broadcast() = 0;
|
||||
virtual bool wait(Mutex* mutex, int timeout=-1) = 0;
|
||||
};
|
||||
|
||||
class Lock
|
||||
{
|
||||
public:
|
||||
Lock(Mutex *m): mutex(m)
|
||||
{
|
||||
mutex->lock();
|
||||
}
|
||||
Lock(Mutex* m);
|
||||
Lock(Mutex& m);
|
||||
~Lock();
|
||||
|
||||
Lock(Mutex &m): mutex(&m)
|
||||
{
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
~Lock()
|
||||
{
|
||||
mutex->unlock();
|
||||
}
|
||||
private:
|
||||
Mutex *mutex;
|
||||
|
||||
Lock(Lock &/* lock*/) {}
|
||||
};
|
||||
|
||||
class Threadable
|
||||
{
|
||||
public:
|
||||
Threadable();
|
||||
virtual ~Threadable();
|
||||
|
||||
virtual void threadFunction() = 0;
|
||||
|
||||
bool start();
|
||||
void wait();
|
||||
void kill();
|
||||
|
||||
protected:
|
||||
Thread *owner;
|
||||
};
|
||||
|
||||
Mutex *newMutex();
|
||||
Conditional *newConditional();
|
||||
Thread *newThread(Threadable *t);
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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()
|
||||
{
|
||||
InitializeCriticalSection(&mutex);
|
||||
}
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
DeleteCriticalSection(&mutex);
|
||||
}
|
||||
|
||||
void Mutex::lock()
|
||||
{
|
||||
EnterCriticalSection(&mutex);
|
||||
}
|
||||
|
||||
void Mutex::unlock()
|
||||
{
|
||||
LeaveCriticalSection(&mutex);
|
||||
}
|
||||
|
||||
int ThreadBase::thread_runner(void *param)
|
||||
{
|
||||
ThreadBase *thread = (ThreadBase *)param;
|
||||
thread->main();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadBase::ThreadBase()
|
||||
: running(false)
|
||||
{
|
||||
}
|
||||
|
||||
ThreadBase::~ThreadBase()
|
||||
{
|
||||
if (running)
|
||||
wait();
|
||||
}
|
||||
|
||||
bool ThreadBase::start()
|
||||
{
|
||||
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread_runner, this, 0, NULL);
|
||||
if (thread == NULL)
|
||||
return false;
|
||||
else
|
||||
return (running = true);
|
||||
}
|
||||
|
||||
void ThreadBase::wait()
|
||||
{
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
running = false;
|
||||
}
|
||||
|
||||
void ThreadBase::kill()
|
||||
{
|
||||
TerminateThread(thread, FALSE);
|
||||
running = false;
|
||||
}
|
||||
|
||||
unsigned int ThreadBase::threadId()
|
||||
{
|
||||
return (unsigned int)GetCurrentThreadId();
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(unsigned int initial_value)
|
||||
: count(initial_value)
|
||||
{
|
||||
semaphore = CreateSemaphore(NULL, initial_value, UINT_MAX, NULL);
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
CloseHandle(semaphore);
|
||||
}
|
||||
|
||||
unsigned int Semaphore::value()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
void Semaphore::post()
|
||||
{
|
||||
InterlockedIncrement(&count);
|
||||
if (ReleaseSemaphore(semaphore, 1, NULL) == FALSE)
|
||||
InterlockedDecrement(&count);
|
||||
}
|
||||
|
||||
bool Semaphore::wait(int timeout)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = WaitForSingleObject(semaphore, timeout < 0 ? INFINITE : timeout);
|
||||
if (result == WAIT_OBJECT_0)
|
||||
{
|
||||
InterlockedDecrement(&count);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Semaphore::tryWait()
|
||||
{
|
||||
return wait(0);
|
||||
}
|
||||
|
||||
|
||||
// Conditional variable implementation based on semaphores.
|
||||
// Vista+ builds should probably use CONDITIONAL_VARIABLE.
|
||||
//
|
||||
// based on http://www.cs.wustl.edu/~schmidt/win32-cv-2.html and ACE
|
||||
|
||||
|
||||
Conditional::Conditional()
|
||||
: waiting(0), signals(0)
|
||||
{
|
||||
}
|
||||
|
||||
Conditional::~Conditional()
|
||||
{
|
||||
}
|
||||
|
||||
void Conditional::signal()
|
||||
{
|
||||
mutex.lock();
|
||||
if (waiting > signals)
|
||||
{
|
||||
signals++;
|
||||
sem.post();
|
||||
mutex.unlock();
|
||||
done.wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void Conditional::broadcast()
|
||||
{
|
||||
mutex.lock();
|
||||
if (waiting > signals)
|
||||
{
|
||||
int num = waiting - signals;
|
||||
signals = waiting;
|
||||
for (int i = 0; i < num; i++)
|
||||
sem.post();
|
||||
mutex.unlock();
|
||||
for (int i = 0; i < num; i++)
|
||||
done.wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool Conditional::wait(Mutex *cmutex, int timeout)
|
||||
{
|
||||
mutex.lock();
|
||||
waiting++;
|
||||
mutex.unlock();
|
||||
|
||||
cmutex->unlock();
|
||||
bool ret = sem.wait(timeout);
|
||||
|
||||
mutex.lock();
|
||||
if (signals > 0)
|
||||
{
|
||||
if (!ret)
|
||||
sem.wait();
|
||||
done.post();
|
||||
signals--;
|
||||
}
|
||||
waiting--;
|
||||
mutex.unlock();
|
||||
cmutex->lock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
@@ -1,107 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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_WIN32_THREADS_H
|
||||
#define LOVE_THREAD_WIN32_THREADS_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <limits.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
CRITICAL_SECTION mutex;
|
||||
Mutex(const Mutex &mutex) {}
|
||||
};
|
||||
|
||||
class ThreadBase
|
||||
{
|
||||
public:
|
||||
ThreadBase();
|
||||
virtual ~ThreadBase();
|
||||
|
||||
bool start();
|
||||
void wait();
|
||||
void kill();
|
||||
|
||||
static unsigned int threadId();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void main() = 0;
|
||||
|
||||
private:
|
||||
HANDLE thread;
|
||||
ThreadBase(ThreadBase &thread) {}
|
||||
bool running;
|
||||
|
||||
static int WINAPI thread_runner(void *param);
|
||||
};
|
||||
|
||||
|
||||
class Semaphore
|
||||
{
|
||||
public:
|
||||
Semaphore(unsigned int initial_value = 0);
|
||||
~Semaphore();
|
||||
|
||||
unsigned int value();
|
||||
void post();
|
||||
bool wait(int timeout = -1);
|
||||
bool tryWait();
|
||||
private:
|
||||
Semaphore(const Semaphore &sem) {}
|
||||
HANDLE semaphore;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
|
||||
// Should conditional inherit from mutex?
|
||||
class Conditional
|
||||
{
|
||||
public:
|
||||
Conditional();
|
||||
~Conditional();
|
||||
|
||||
void signal();
|
||||
void broadcast();
|
||||
bool wait(Mutex *cmutex, int timeout=-1);
|
||||
private:
|
||||
Mutex mutex;
|
||||
int waiting;
|
||||
int signals;
|
||||
Semaphore sem;
|
||||
Semaphore done;
|
||||
};
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif /* LOVE_THREAD_WIN32_THREADS_H */
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* 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_Channel.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
Channel *luax_checkchannel(lua_State *L, int idx)
|
||||
{
|
||||
return luax_checktype<Channel>(L, idx, "Channel", THREAD_CHANNEL_T);
|
||||
}
|
||||
|
||||
int w_Channel_push(lua_State *L)
|
||||
{
|
||||
Channel *c = luax_checkchannel(L, 1);
|
||||
Variant *var = Variant::fromLua(L, 2);
|
||||
c->push(var);
|
||||
var->release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Channel_pop(lua_State *L)
|
||||
{
|
||||
Channel *c = luax_checkchannel(L, 1);
|
||||
Variant *var = c->pop();
|
||||
if (var)
|
||||
{
|
||||
var->toLua(L);
|
||||
var->release();
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Channel_demand(lua_State *L)
|
||||
{
|
||||
Channel *c = luax_checkchannel(L, 1);
|
||||
Variant *var = c->demand();
|
||||
var->toLua(L);
|
||||
var->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Channel_peek(lua_State *L)
|
||||
{
|
||||
Channel *c = luax_checkchannel(L, 1);
|
||||
Variant *var = c->peek();
|
||||
if (var)
|
||||
{
|
||||
var->toLua(L);
|
||||
var->release();
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Channel_count(lua_State *L)
|
||||
{
|
||||
Channel *c = luax_checkchannel(L, 1);
|
||||
lua_pushnumber(L, c->count());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Channel_clear(lua_State *L)
|
||||
{
|
||||
Channel *c = luax_checkchannel(L, 1);
|
||||
c->clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg type_functions[] = {
|
||||
{ "push", w_Channel_push },
|
||||
{ "pop", w_Channel_pop },
|
||||
{ "demand", w_Channel_demand },
|
||||
{ "peek", w_Channel_peek },
|
||||
{ "count", w_Channel_count },
|
||||
{ "clear", w_Channel_clear },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
extern "C" int luaopen_channel(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, "Channel", type_functions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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_WRAP_CHANNEL_H
|
||||
#define LOVE_THREAD_WRAP_CHANNEL_H
|
||||
|
||||
// LOVE
|
||||
#include "Channel.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
Channel *luax_checkchannel(lua_State *L, int idx);
|
||||
int w_Channel_push(lua_State *L);
|
||||
int w_Channel_pop(lua_State *L);
|
||||
int w_Channel_demand(lua_State *L);
|
||||
int w_Channel_peek(lua_State *L);
|
||||
int w_Channel_count(lua_State *L);
|
||||
int w_Channel_clear(lua_State *L);
|
||||
|
||||
extern "C" int luaopen_channel(lua_State *L);
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_WRAP_CHANNEL_H
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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_LuaThread.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
LuaThread *luax_checkthread(lua_State *L, int idx)
|
||||
{
|
||||
return luax_checktype<LuaThread>(L, idx, "Thread", THREAD_THREAD_T);
|
||||
}
|
||||
|
||||
int w_Thread_start(lua_State *L)
|
||||
{
|
||||
LuaThread *t = luax_checkthread(L, 1);
|
||||
luax_pushboolean(L, t->start());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Thread_wait(lua_State *L)
|
||||
{
|
||||
LuaThread *t = luax_checkthread(L, 1);
|
||||
t->wait();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Thread_getError(lua_State *L)
|
||||
{
|
||||
LuaThread *t = luax_checkthread(L, 1);
|
||||
std::string err = t->getError();
|
||||
if (err.length() == 0)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
luax_pushstring(L, err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg type_functions[] = {
|
||||
{ "start", w_Thread_start },
|
||||
{ "wait", w_Thread_wait },
|
||||
{ "getError", w_Thread_getError },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
extern "C" int luaopen_thread(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, "Thread", type_functions);
|
||||
}
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
@@ -18,37 +18,25 @@
|
||||
* 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
|
||||
#ifndef LOVE_THREAD_WRAP_LUATHREAD_H
|
||||
#define LOVE_THREAD_WRAP_LUATHREAD_H
|
||||
|
||||
// LOVE
|
||||
#include "common/config.h"
|
||||
#include "Thread.h"
|
||||
#include "ThreadModule.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
Thread *luax_checkthread(lua_State *L, int idx);
|
||||
LuaThread *luax_checkthread(lua_State *L, int idx);
|
||||
int w_Thread_start(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_getKeys(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 w_Thread_getError(lua_State *L);
|
||||
|
||||
extern "C" 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);
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_SDL_WRAP_THREAD_H
|
||||
#endif // LOVE_THREAD_WRAP_LUATHREAD_H
|
||||
@@ -1,290 +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"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
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_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
|
||||
luax_pushstring(L, t->getName());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int w_Thread_get(lua_State *L)
|
||||
{
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
std::string name = luax_checkstring(L, 2);
|
||||
t->lock();
|
||||
Variant *v = t->get(name);
|
||||
t->clear(name);
|
||||
t->unlock();
|
||||
if (!v)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
v->toLua(L);
|
||||
t->lock();
|
||||
v->release();
|
||||
t->unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Thread_getKeys(lua_State *L)
|
||||
{
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
t->lock();
|
||||
std::vector<std::string> keys = t->getKeys();
|
||||
t->unlock();
|
||||
lua_createtable(L, keys.size(), 0);
|
||||
int i = 1;
|
||||
for (std::vector<std::string>::iterator it = keys.begin(); it != keys.end(); it++)
|
||||
{
|
||||
lua_pushnumber(L, i++);
|
||||
luax_pushstring(L, *it);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Thread_demand(lua_State *L)
|
||||
{
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
std::string name = luax_checkstring(L, 2);
|
||||
t->lock();
|
||||
Variant *v = t->demand(name);
|
||||
t->clear(name);
|
||||
t->unlock();
|
||||
if (!v)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
v->toLua(L);
|
||||
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_checkstring(L, 2);
|
||||
t->lock();
|
||||
Variant *v = t->get(name);
|
||||
t->unlock();
|
||||
if (!v)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
v->toLua(L);
|
||||
t->lock();
|
||||
v->release();
|
||||
t->unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int w_Thread_set(lua_State *L)
|
||||
{
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
std::string name = luax_checkstring(L, 2);
|
||||
Variant *v = Variant::fromLua(L, 3);
|
||||
if (!v)
|
||||
return luaL_error(L, "Expected boolean, number, string or userdata");
|
||||
t->set(name, v);
|
||||
t->lock();
|
||||
v->release();
|
||||
t->unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg type_functions[] =
|
||||
{
|
||||
{ "start", w_Thread_start },
|
||||
{ "wait", w_Thread_wait },
|
||||
{ "getName", w_Thread_getName },
|
||||
{ "get", w_Thread_get },
|
||||
{ "getKeys", w_Thread_getKeys },
|
||||
{ "demand", w_Thread_demand },
|
||||
{ "peek", w_Thread_peek },
|
||||
{ "set", w_Thread_set },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
extern "C" 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_checkstring(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);
|
||||
data->retain();
|
||||
}
|
||||
Thread *t = instance->newThread(name, data);
|
||||
// do not worry, file->read() returns retained data
|
||||
data->release();
|
||||
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
|
||||
luax_pushstring(L, list[i]->getName());
|
||||
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_checkstring(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
|
||||
};
|
||||
|
||||
extern "C" 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);
|
||||
}
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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_ThreadModule.h"
|
||||
#include "wrap_LuaThread.h"
|
||||
#include "wrap_Channel.h"
|
||||
#include <filesystem/File.h>
|
||||
#include <filesystem/FileData.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
static ThreadModule *instance = 0;
|
||||
|
||||
int w_newThread(lua_State *L)
|
||||
{
|
||||
std::string name = "Thread code";
|
||||
love::Data *data;
|
||||
if (lua_isstring(L, 1))
|
||||
luax_convobj(L, 1, "filesystem", "newFile");
|
||||
if (luax_istype(L, 1, FILESYSTEM_FILE_T))
|
||||
{
|
||||
try
|
||||
{
|
||||
love::filesystem::File * file = luax_checktype<love::filesystem::File>(L, 1, "File", FILESYSTEM_FILE_T);
|
||||
name = std::string("@") + file->getFilename();
|
||||
data = file->read();
|
||||
}
|
||||
catch (love::Exception & e)
|
||||
{
|
||||
return luaL_error(L, "%s", e.what());
|
||||
}
|
||||
}
|
||||
else if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
|
||||
{
|
||||
love::filesystem::FileData * fdata = luax_checktype<love::filesystem::FileData>(L, 1, "FileData", FILESYSTEM_FILE_DATA_T);
|
||||
name = std::string("@") + fdata->getFilename();
|
||||
data = fdata;
|
||||
data->retain();
|
||||
}
|
||||
else
|
||||
{
|
||||
data = luax_checktype<love::Data>(L, 1, "Data", DATA_T);
|
||||
data->retain();
|
||||
}
|
||||
LuaThread *t = instance->newThread(name, data);
|
||||
// do not worry, file->read() returns retained data
|
||||
data->release();
|
||||
luax_newtype(L, "Thread", THREAD_THREAD_T, (void*)t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newChannel(lua_State *L)
|
||||
{
|
||||
Channel *c = instance->newChannel();
|
||||
luax_newtype(L, "Channel", THREAD_CHANNEL_T, (void*)c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getChannel(lua_State *L)
|
||||
{
|
||||
std::string name = luax_checkstring(L, 1);
|
||||
Channel *c = instance->getChannel(name);
|
||||
luax_newtype(L, "Channel", THREAD_CHANNEL_T, (void*)c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// List of functions to wrap.
|
||||
static const luaL_Reg module_functions[] = {
|
||||
{ "newThread", w_newThread },
|
||||
{ "newChannel", w_newChannel },
|
||||
{ "getChannel", w_getChannel },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const lua_CFunction types[] = {
|
||||
luaopen_thread,
|
||||
luaopen_channel,
|
||||
0
|
||||
};
|
||||
|
||||
extern "C" int luaopen_love_thread(lua_State *L)
|
||||
{
|
||||
if (instance == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
instance = new ThreadModule();
|
||||
}
|
||||
catch (Exception & e)
|
||||
{
|
||||
return luaL_error(L, "%s", 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2012 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_WRAP_THREADMODULE_H
|
||||
#define LOVE_THREAD_WRAP_THREADMODULE_H
|
||||
|
||||
// LOVE
|
||||
#include "ThreadModule.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
int w_newThread(lua_State *L);
|
||||
int w_newChannel(lua_State *L);
|
||||
int w_getChannel(lua_State *L);
|
||||
|
||||
extern "C" LOVE_EXPORT int luaopen_love_thread(lua_State * L);
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
#endif // LOVE_THREAD_WRAP_THREADMODULE_H
|
||||
Reference in New Issue
Block a user