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:
Bart van Strien
2012-07-04 17:15:16 +02:00
parent e8ee7671c3
commit 399a6a6614
41 changed files with 1192 additions and 1580 deletions
+10 -2
View File
@@ -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.
+4 -4
View File
@@ -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;
+1 -1
View File
@@ -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.");
+6
View File
@@ -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)
+2 -2
View File
@@ -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
+12
View File
@@ -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;
+4 -2
View File
@@ -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);
+7 -1
View File
@@ -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);
+5
View File
@@ -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
+148
View File
@@ -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
+61
View File
@@ -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
+68
View File
@@ -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
+52
View File
@@ -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
-317
View File
@@ -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
View File
@@ -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
+49
View File
@@ -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
+52
View File
@@ -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
-192
View File
@@ -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
-107
View File
@@ -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
+90
View File
@@ -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
+57
View File
@@ -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
+25 -86
View File
@@ -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
+31 -67
View File
@@ -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 */
+39 -16
View File
@@ -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
+43 -45
View File
@@ -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
-211
View File
@@ -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
-107
View File
@@ -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 */
+107
View File
@@ -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);
}
}
}
+43
View File
@@ -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
+71
View File
@@ -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
-290
View File
@@ -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
+126
View File
@@ -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);
}
}
}
+40
View File
@@ -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