mirror of
https://github.com/love2d/love.git
synced 2026-08-18 03:34:23 +02:00
Multiple thread backends.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
|
||||
#include "delay.h"
|
||||
|
||||
namespace love {
|
||||
|
||||
void delay(unsigned int ms) {
|
||||
#if LOVE_THREADS == LOVE_THREADS_POSIX
|
||||
struct timespec ts1, ts2;
|
||||
|
||||
ts1.tv_sec = ms / 1000;
|
||||
ts1.tv_nsec = (ms % 1000) * 1000000;
|
||||
// FIXME: handle signals
|
||||
nanosleep(&ts1, &ts2);
|
||||
#elif LOVE_THREADS == LOVE_THREADS_WIN32
|
||||
Sleep(ms);
|
||||
#elif LOVE_THREADS == LOVE_THREADS_SDL
|
||||
SDL_Delay(ms);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace love
|
||||
@@ -18,24 +18,16 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_THREAD_THREAD_H
|
||||
#define LOVE_THREAD_THREAD_H
|
||||
#ifndef DELAY_H_
|
||||
#define DELAY_H_
|
||||
|
||||
#include <common/Module.h>
|
||||
#include <string>
|
||||
#include <thread/threads.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
class ThreadModule : public Module
|
||||
{
|
||||
public:
|
||||
virtual ~ThreadModule(){};
|
||||
virtual void unregister(const std::string & name) = 0;
|
||||
}; // ThreadModule
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
namespace love {
|
||||
|
||||
#endif // LOVE_THREAD_THREAD_H
|
||||
void delay(unsigned int ms);
|
||||
|
||||
}; // namespace love
|
||||
|
||||
#endif /* DELAY_H_ */
|
||||
@@ -25,17 +25,15 @@
|
||||
#include "Object.h"
|
||||
#include "Reference.h"
|
||||
#include "StringMap.h"
|
||||
#include <thread/threads.h>
|
||||
|
||||
// STD
|
||||
#include <iostream>
|
||||
|
||||
// SDL
|
||||
#include <SDL_mutex.h>
|
||||
#include <SDL_thread.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
static SDL_mutex *gcmutex = 0;
|
||||
static thread::Mutex *gcmutex = 0;
|
||||
void *_gcmutex = 0;
|
||||
unsigned int _gcthread = 0;
|
||||
/**
|
||||
@@ -46,17 +44,16 @@ namespace love
|
||||
{
|
||||
if (!gcmutex)
|
||||
{
|
||||
gcmutex = SDL_CreateMutex();
|
||||
gcmutex = new thread::Mutex();
|
||||
_gcmutex = (void*) gcmutex;
|
||||
}
|
||||
Proxy * p = (Proxy *)lua_touserdata(L, 1);
|
||||
Object * t = (Object *)p->data;
|
||||
if(p->own)
|
||||
{
|
||||
SDL_mutexP(gcmutex);
|
||||
_gcthread = (unsigned int) SDL_ThreadID();
|
||||
thread::Lock lock(gcmutex);
|
||||
_gcthread = thread::ThreadBase::threadId();
|
||||
t->release();
|
||||
SDL_mutexV(gcmutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@
|
||||
#include <physics/box2d/wrap_Physics.h>
|
||||
#include <sound/wrap_Sound.h>
|
||||
#include <timer/sdl/wrap_Timer.h>
|
||||
#include <thread/sdl/wrap_Thread.h>
|
||||
#include <thread/wrap_Thread.h>
|
||||
|
||||
// Libraries.
|
||||
#include "libraries/luasocket/luasocket.h"
|
||||
@@ -77,7 +77,7 @@ static const luaL_Reg modules[] = {
|
||||
{ "love.physics", love::physics::box2d::luaopen_love_physics },
|
||||
{ "love.sound", love::sound::luaopen_love_sound },
|
||||
{ "love.timer", love::timer::sdl::luaopen_love_timer },
|
||||
{ "love.thread", love::thread::sdl::luaopen_love_thread },
|
||||
{ "love.thread", love::thread::luaopen_love_thread },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
**/
|
||||
|
||||
#include "Audio.h"
|
||||
#include <common/delay.h>
|
||||
|
||||
#include <sound/Decoder.h>
|
||||
|
||||
@@ -28,8 +29,34 @@ namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
Audio::PoolThread::PoolThread(Pool* pool)
|
||||
: pool(pool), finish(false) {
|
||||
|
||||
}
|
||||
|
||||
void Audio::PoolThread::main()
|
||||
{
|
||||
while(true) {
|
||||
{
|
||||
thread::Lock lock(mutex);
|
||||
if (finish) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pool->update();
|
||||
delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::PoolThread::setFinish()
|
||||
{
|
||||
thread::Lock lock(mutex);
|
||||
finish = true;
|
||||
}
|
||||
|
||||
|
||||
Audio::Audio()
|
||||
: finish(false)
|
||||
{
|
||||
// Passing zero for default device.
|
||||
device = alcOpenDevice(0);
|
||||
@@ -67,15 +94,16 @@ namespace openal
|
||||
// pool must be allocated after AL context.
|
||||
pool = new Pool();
|
||||
|
||||
thread = SDL_CreateThread(Audio::run, (void*)this);
|
||||
poolThread = new PoolThread(pool);
|
||||
poolThread->start();
|
||||
}
|
||||
|
||||
Audio::~Audio()
|
||||
{
|
||||
finish = true;
|
||||
|
||||
SDL_WaitThread(thread, 0);
|
||||
poolThread->setFinish();
|
||||
poolThread->wait();
|
||||
|
||||
delete poolThread;
|
||||
delete pool;
|
||||
|
||||
alcMakeContextCurrent(0);
|
||||
@@ -84,18 +112,6 @@ namespace openal
|
||||
alcCloseDevice(device);
|
||||
}
|
||||
|
||||
int Audio::run(void * d)
|
||||
{
|
||||
Audio * instance = (Audio*)d;
|
||||
|
||||
while(!instance->finish)
|
||||
{
|
||||
instance->pool->update();
|
||||
SDL_Delay(5);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char * Audio::getName() const
|
||||
{
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "Source.h"
|
||||
#include "Pool.h"
|
||||
#include <thread/threads.h>
|
||||
|
||||
// OpenAL
|
||||
#ifdef LOVE_MACOSX
|
||||
@@ -66,17 +67,30 @@ namespace openal
|
||||
// The OpenAL context.
|
||||
ALCcontext * context;
|
||||
|
||||
SDL_Thread * thread;
|
||||
|
||||
// The Pool.
|
||||
Pool * pool;
|
||||
|
||||
// Set this to true when the thread should finish.
|
||||
// Main thread will write to this value, and Audio::run
|
||||
// will read from it.
|
||||
bool finish;
|
||||
|
||||
static int run(void * unused);
|
||||
class PoolThread: public thread::ThreadBase {
|
||||
protected:
|
||||
Pool* pool;
|
||||
|
||||
// Set this to true when the thread should finish.
|
||||
// Main thread will write to this value, and PoolThread
|
||||
// will read from it.
|
||||
volatile bool finish;
|
||||
|
||||
// finish lock
|
||||
thread::Mutex mutex;
|
||||
|
||||
virtual void main();
|
||||
|
||||
public:
|
||||
PoolThread(Pool* pool);
|
||||
void setFinish();
|
||||
};
|
||||
|
||||
PoolThread* poolThread;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace openal
|
||||
alGenSources(NUM_SOURCES, sources);
|
||||
|
||||
// Create the mutex.
|
||||
mutex = SDL_CreateMutex();
|
||||
mutex = new thread::Mutex();
|
||||
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
throw love::Exception("Could not generate sources.");
|
||||
@@ -58,7 +58,7 @@ namespace openal
|
||||
{
|
||||
stop();
|
||||
|
||||
SDL_DestroyMutex(mutex);
|
||||
delete mutex;
|
||||
|
||||
// Free all sources.
|
||||
alDeleteSources(NUM_SOURCES, sources);
|
||||
@@ -67,28 +67,30 @@ namespace openal
|
||||
bool Pool::isAvailable() const
|
||||
{
|
||||
bool has = false;
|
||||
LOCK(mutex);
|
||||
has = !available.empty();
|
||||
UNLOCK(mutex);
|
||||
{
|
||||
thread::Lock lock(mutex);
|
||||
has = !available.empty();
|
||||
}
|
||||
return has;
|
||||
}
|
||||
|
||||
bool Pool::isPlaying(Source * s)
|
||||
{
|
||||
bool p = false;
|
||||
LOCK(mutex);
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
{
|
||||
if(i->first == s)
|
||||
p = true;
|
||||
thread::Lock lock(mutex);
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
{
|
||||
if(i->first == s)
|
||||
p = true;
|
||||
}
|
||||
}
|
||||
UNLOCK(mutex);
|
||||
return p;
|
||||
}
|
||||
|
||||
void Pool::update()
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
|
||||
std::map<Source *, ALuint>::iterator i = playing.begin();
|
||||
|
||||
@@ -107,8 +109,6 @@ namespace openal
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
int Pool::getNumSources() const
|
||||
@@ -126,7 +126,7 @@ namespace openal
|
||||
bool ok;
|
||||
out = 0;
|
||||
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
|
||||
bool alreadyPlaying = findSource(source, out);
|
||||
|
||||
@@ -160,14 +160,12 @@ namespace openal
|
||||
ok = true;
|
||||
}
|
||||
|
||||
UNLOCK(mutex);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void Pool::stop()
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
{
|
||||
i->first->stopAtomic();
|
||||
@@ -175,66 +173,57 @@ namespace openal
|
||||
}
|
||||
|
||||
playing.clear();
|
||||
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::stop(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
removeSource(source);
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::pause()
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->pauseAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::pause(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
ALuint out;
|
||||
if(findSource(source, out))
|
||||
source->pauseAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::resume()
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->resumeAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::resume(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
ALuint out;
|
||||
if(findSource(source, out))
|
||||
source->resumeAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::rewind()
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->rewindAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::rewind(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
thread::Lock lock(mutex);
|
||||
ALuint out;
|
||||
if(findSource(source, out))
|
||||
source->rewindAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::release(Source * source)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
// LOVE
|
||||
#include <common/config.h>
|
||||
#include <common/Exception.h>
|
||||
#include <thread/threads.h>
|
||||
|
||||
// OpenAL
|
||||
#ifdef LOVE_MACOSX
|
||||
@@ -70,7 +71,7 @@ namespace openal
|
||||
|
||||
// Only one thread can access this object at the same time. This mutex will
|
||||
// make sure of that.
|
||||
SDL_mutex * mutex;
|
||||
thread::Mutex* mutex;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -31,10 +31,14 @@ namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
int threadfunc(ThreadData *comm)
|
||||
|
||||
Thread::ThreadThread::ThreadThread(ThreadData* comm)
|
||||
: comm(comm)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Thread::ThreadThread::main() {
|
||||
lua_State * L = lua_open();
|
||||
luaL_openlibs(L);
|
||||
#ifdef LOVE_BUILD_STANDALONE
|
||||
@@ -53,17 +57,18 @@ namespace sdl
|
||||
lua_setfield(L, -2, "_curthread");
|
||||
if(luaL_dostring(L, comm->getCode()) == 1)
|
||||
{
|
||||
SDL_mutexP((SDL_mutex*) comm->mutex);
|
||||
ThreadVariant *v = new ThreadVariant(lua_tostring(L, -1), lua_strlen(L, -1));
|
||||
comm->setValue("error", v);
|
||||
v->release();
|
||||
SDL_mutexV((SDL_mutex*) comm->mutex);
|
||||
SDL_CondBroadcast((SDL_cond*) comm->cond);
|
||||
{
|
||||
Lock lock((Mutex*) comm->mutex);
|
||||
ThreadVariant *v = new ThreadVariant(lua_tostring(L, -1), lua_strlen(L, -1));
|
||||
comm->setValue("error", v);
|
||||
v->release();
|
||||
}
|
||||
((Conditional*) comm->cond)->broadcast();
|
||||
}
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ThreadVariant::ThreadVariant(bool boolean)
|
||||
{
|
||||
type = BOOLEAN;
|
||||
@@ -183,8 +188,8 @@ namespace sdl
|
||||
this->data = new char[len+1];
|
||||
memset(this->data, 0, len+1);
|
||||
memcpy(this->data, data->getData(), len);
|
||||
mutex = SDL_CreateMutex();
|
||||
cond = SDL_CreateCond();
|
||||
mutex = new Mutex();
|
||||
cond = new Conditional();
|
||||
comm = new ThreadData(name.c_str(), name.length(), this->data, mutex, cond);
|
||||
}
|
||||
|
||||
@@ -192,8 +197,8 @@ namespace sdl
|
||||
: handle(0), module(module), name(name), data(0), isThread(false)
|
||||
{
|
||||
module->retain();
|
||||
mutex = SDL_CreateMutex();
|
||||
cond = SDL_CreateCond();
|
||||
mutex = new Mutex();
|
||||
cond = new Conditional();
|
||||
comm = new ThreadData(name.c_str(), name.length(), NULL, mutex, cond);
|
||||
}
|
||||
|
||||
@@ -203,25 +208,27 @@ namespace sdl
|
||||
delete[] data;
|
||||
delete comm;
|
||||
module->unregister(name);
|
||||
SDL_DestroyMutex(mutex);
|
||||
SDL_DestroyCond(cond);
|
||||
delete mutex;
|
||||
delete cond;
|
||||
module->release();
|
||||
}
|
||||
|
||||
void Thread::start()
|
||||
{
|
||||
if (!handle && isThread)
|
||||
handle = SDL_CreateThread((int (*)(void*)) threadfunc, (void*) comm);
|
||||
if (!handle && isThread) {
|
||||
handle = new ThreadThread(comm);
|
||||
handle->start();
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::kill()
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
SDL_mutexP((SDL_mutex *) _gcmutex);
|
||||
SDL_KillThread(handle);
|
||||
Lock lock((Mutex *) _gcmutex);
|
||||
handle->kill();
|
||||
delete handle;
|
||||
handle = 0;
|
||||
SDL_mutexV((SDL_mutex *) _gcmutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,19 +236,20 @@ namespace sdl
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
SDL_WaitThread(handle, NULL);
|
||||
handle->wait();
|
||||
delete handle;
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::lock()
|
||||
{
|
||||
SDL_mutexP(mutex);
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
void Thread::unlock()
|
||||
{
|
||||
SDL_mutexV(mutex);
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
std::string Thread::getName()
|
||||
@@ -264,7 +272,7 @@ namespace sdl
|
||||
{
|
||||
if (comm->getValue("error"))
|
||||
return 0;
|
||||
SDL_CondWait(cond, mutex);
|
||||
cond->wait(mutex);
|
||||
v = comm->getValue(name);
|
||||
}
|
||||
v->retain();
|
||||
@@ -281,7 +289,7 @@ namespace sdl
|
||||
lock(); //this function explicitly locks
|
||||
comm->setValue(name, v); //because we need
|
||||
unlock(); //it to unlock here for the cond
|
||||
SDL_CondBroadcast(cond);
|
||||
cond->broadcast();
|
||||
}
|
||||
|
||||
ThreadModule::ThreadModule()
|
||||
@@ -294,6 +302,7 @@ namespace sdl
|
||||
for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++)
|
||||
{
|
||||
i->second->kill();
|
||||
delete i->second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,6 +342,7 @@ namespace sdl
|
||||
if (threads.count(name) == 0)
|
||||
return;
|
||||
threadlist_t::iterator i = threads.find(name);
|
||||
// FIXME: shouldn't the thread be deleted?
|
||||
threads.erase(i);
|
||||
}
|
||||
|
||||
@@ -340,6 +350,6 @@ namespace sdl
|
||||
{
|
||||
return "love.thread.sdl";
|
||||
}
|
||||
} // sdl
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
@@ -21,25 +21,24 @@
|
||||
#ifndef LOVE_THREAD_SDL_THREAD_H
|
||||
#define LOVE_THREAD_SDL_THREAD_H
|
||||
|
||||
// SDL
|
||||
#include <SDL_thread.h>
|
||||
#include <SDL_mutex.h>
|
||||
|
||||
// STL
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// LOVE
|
||||
#include <thread/ThreadModule.h>
|
||||
#include <filesystem/File.h>
|
||||
#include <common/runtime.h>
|
||||
#include <common/Module.h>
|
||||
#include <thread/threads.h>
|
||||
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
class ThreadModule;
|
||||
|
||||
enum ThreadVariantType
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
@@ -98,15 +97,28 @@ namespace sdl
|
||||
class Thread : public love::Object
|
||||
{
|
||||
private:
|
||||
SDL_Thread *handle;
|
||||
love::thread::ThreadModule *module;
|
||||
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;
|
||||
SDL_mutex *mutex;
|
||||
SDL_cond *cond;
|
||||
Mutex *mutex;
|
||||
Conditional *cond;
|
||||
bool isThread;
|
||||
|
||||
|
||||
public:
|
||||
Thread(love::thread::ThreadModule *module, const std::string & name, love::Data *data);
|
||||
Thread(love::thread::ThreadModule *module, const std::string & name);
|
||||
@@ -125,7 +137,7 @@ namespace sdl
|
||||
|
||||
typedef std::map<std::string, Thread*> threadlist_t;
|
||||
|
||||
class ThreadModule : public love::thread::ThreadModule
|
||||
class ThreadModule : public love::Module
|
||||
{
|
||||
private:
|
||||
threadlist_t threads;
|
||||
@@ -140,7 +152,6 @@ namespace sdl
|
||||
void unregister(const std::string & name);
|
||||
const char *getName() const;
|
||||
}; // ThreadModule
|
||||
} // sdl
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "threads.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
Mutex::Mutex() {
|
||||
pthread_create_mutex(&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;
|
||||
} else {
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ThreadBase::wait() {
|
||||
pthread_join(thread, NULL);
|
||||
running = false;
|
||||
}
|
||||
|
||||
|
||||
void ThreadBase::kill() {
|
||||
// FIXME: I'm not sure about that one.
|
||||
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) {
|
||||
if (sem_wait(&sem)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else if (timeout == 0) {
|
||||
if (sem_trywait(&sem)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = timeout/1000;
|
||||
ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||
if (sem_timedwait(&sem, &ts)) {
|
||||
return false; // either timeout or error...
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Semaphore::tryWait() {
|
||||
if (sem_trywait(&sem)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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) {
|
||||
if (pthread_cond_wait(cond, mutex->mutex)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} 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);
|
||||
if (ret == ETIMEDOUT) {
|
||||
return false;
|
||||
} else if (ret == 0) {
|
||||
return true;
|
||||
} else {
|
||||
// something bad happend!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_PLATFORM_POSIX_THREADS_H_
|
||||
#define LOVE_PLATFORM_POSIX_THREADS_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
class Mutex {
|
||||
private:
|
||||
pthread_mutex_t mutex;
|
||||
Mutex(const Mutex& mutex) {}
|
||||
|
||||
friend class Conditional;
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
|
||||
class ThreadBase {
|
||||
private:
|
||||
pthread_t thread;
|
||||
ThreadBase(ThreadBase& thread) {}
|
||||
|
||||
static void* thread_runner(void* param);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void main() = 0;
|
||||
|
||||
public:
|
||||
ThreadBase();
|
||||
virtual ~ThreadBase();
|
||||
|
||||
bool start();
|
||||
void wait();
|
||||
void kill();
|
||||
|
||||
static unsigned int threadId();
|
||||
};
|
||||
|
||||
class Semaphore {
|
||||
private:
|
||||
Semaphore(const Semaphore& sem) {}
|
||||
sem_t semaphore;
|
||||
|
||||
public:
|
||||
Semaphore(unsigned int initial_value);
|
||||
~Semaphore();
|
||||
|
||||
unsigned int value();
|
||||
void post();
|
||||
bool wait(int timeout = -1);
|
||||
bool tryWait();
|
||||
};
|
||||
|
||||
// Should conditional inherit from mutex?
|
||||
class Conditional {
|
||||
private:
|
||||
pthread_cond_t cond;
|
||||
|
||||
public:
|
||||
Conditional();
|
||||
~Conditional();
|
||||
|
||||
void signal();
|
||||
void broadcast();
|
||||
bool wait(Mutex* mutex, int timeout=-1);
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
|
||||
|
||||
#endif // !LOVE_PLATFORM_POSIX_THREADS_H_
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "threads.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
Mutex::Mutex() {
|
||||
mutex = SDL_CreateMutex();
|
||||
}
|
||||
|
||||
Mutex::~Mutex() {
|
||||
SDL_DestroyMutex(mutex);
|
||||
}
|
||||
|
||||
void Mutex::lock() {
|
||||
SDL_mutexP(mutex);
|
||||
}
|
||||
|
||||
void Mutex::unlock() {
|
||||
SDL_mutexV(mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ThreadBase::thread_runner(void* param) {
|
||||
ThreadBase* thread = (ThreadBase*)param;
|
||||
thread->main();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadBase::ThreadBase() : running(false) {
|
||||
SDL_Thread* thread;
|
||||
}
|
||||
|
||||
ThreadBase::~ThreadBase() {
|
||||
if (running) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
bool ThreadBase::start() {
|
||||
thread = SDL_CreateThread(thread_runner, this);
|
||||
if (thread == NULL) {
|
||||
return false;
|
||||
} else {
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadBase::wait() {
|
||||
SDL_WaitThread(thread, NULL);
|
||||
running = false;
|
||||
}
|
||||
|
||||
void ThreadBase::kill() {
|
||||
SDL_KillThread(thread);
|
||||
running = false;
|
||||
}
|
||||
|
||||
unsigned int ThreadBase::threadId() {
|
||||
return (unsigned int)SDL_ThreadID();
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(unsigned int initial_value) {
|
||||
semaphore = SDL_CreateSemaphore(initial_value);
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore() {
|
||||
SDL_DestroySemaphore(semaphore);
|
||||
}
|
||||
|
||||
unsigned int Semaphore::value() {
|
||||
return SDL_SemValue(semaphore);
|
||||
}
|
||||
|
||||
void Semaphore::post() {
|
||||
SDL_SemPost(semaphore);
|
||||
}
|
||||
|
||||
bool Semaphore::wait(int timeout) {
|
||||
if (timeout < 0) {
|
||||
return SDL_SemWait(semaphore) ? false : true;
|
||||
} else if (timeout == 0) {
|
||||
return SDL_SemTryWait(semaphore) ? false : true;
|
||||
} else {
|
||||
int ret = SDL_SemWaitTimeout(semaphore, timeout);
|
||||
if (ret == SDL_MUTEX_TIMEDOUT) {
|
||||
return false;
|
||||
} else if (ret == 0) {
|
||||
return true;
|
||||
} else {
|
||||
// some nasty error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Semaphore::tryWait() {
|
||||
return SDL_SemTryWait(semaphore) ? false : true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Conditional::Conditional() {
|
||||
cond = SDL_CreateCond();
|
||||
}
|
||||
|
||||
Conditional::~Conditional() {
|
||||
SDL_DestroyCond(cond);
|
||||
}
|
||||
|
||||
void Conditional::signal() {
|
||||
SDL_CondSignal(cond);
|
||||
}
|
||||
|
||||
void Conditional::broadcast() {
|
||||
SDL_CondBroadcast(cond);
|
||||
}
|
||||
|
||||
bool Conditional::wait(Mutex* mutex, int timeout) {
|
||||
if (timeout < 0) {
|
||||
if (SDL_CondWait(cond, mutex->mutex)) {
|
||||
// error
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
int ret = SDL_CondWaitTimeout(cond, mutex->mutex, timeout);
|
||||
if (ret == SDL_MUTEX_TIMEDOUT) {
|
||||
return false;
|
||||
} else if (ret == 0) {
|
||||
return true;
|
||||
} else {
|
||||
// some bad error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_PLATFORM_SDL_THREADS_H_
|
||||
#define LOVE_PLATFORM_SDL_THREADS_H_
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
class Mutex {
|
||||
private:
|
||||
SDL_mutex* mutex;
|
||||
Mutex(const Mutex& mutex) {}
|
||||
|
||||
friend class Conditional;
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ThreadBase {
|
||||
private:
|
||||
SDL_Thread* thread;
|
||||
ThreadBase(ThreadBase& thread) {}
|
||||
bool running;
|
||||
|
||||
static int thread_runner(void* param);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void main() = 0;
|
||||
|
||||
public:
|
||||
ThreadBase();
|
||||
virtual ~ThreadBase();
|
||||
|
||||
bool start();
|
||||
void wait();
|
||||
void kill(); // FIXME: not supported by SDL (SDL's kill is probably cancel)?
|
||||
|
||||
static unsigned int threadId();
|
||||
};
|
||||
|
||||
class Semaphore {
|
||||
private:
|
||||
Semaphore(const Semaphore& sem) {}
|
||||
SDL_sem* semaphore;
|
||||
|
||||
public:
|
||||
Semaphore(unsigned int initial_value);
|
||||
~Semaphore();
|
||||
|
||||
unsigned int value();
|
||||
void post();
|
||||
bool wait(int timeout = -1);
|
||||
bool tryWait();
|
||||
};
|
||||
|
||||
// Should conditional inherit from mutex?
|
||||
class Conditional {
|
||||
private:
|
||||
SDL_cond* cond;
|
||||
|
||||
public:
|
||||
Conditional();
|
||||
~Conditional();
|
||||
|
||||
void signal();
|
||||
void broadcast();
|
||||
bool wait(Mutex* mutex, int timeout=-1);
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
|
||||
|
||||
#endif // !LOVE_PLATFORM_SDL_THREADS_H_
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "threads.h"
|
||||
|
||||
#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() {
|
||||
#if LOVE_THREADS == LOVE_THREADS_POSIX
|
||||
return "posix";
|
||||
#elif LOVE_THREADS == LOVE_THREADS_WIN32
|
||||
return "win32";
|
||||
#elif LOVE_THREADS == LOVE_THREADS_SDL
|
||||
return "sdl";
|
||||
#else
|
||||
return "unknown"; // ?!?!?!
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_THREADS_H_
|
||||
#define LOVE_THREADS_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
|
||||
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
const char* threadAPI();
|
||||
|
||||
class Lock {
|
||||
private:
|
||||
Mutex* mutex;
|
||||
|
||||
Lock(Lock& lock) {}
|
||||
|
||||
public:
|
||||
Lock(Mutex* m): mutex(m) {
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
Lock(Mutex& m): mutex(&m) {
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
~Lock() {
|
||||
mutex->unlock();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
|
||||
#endif /* LOVE_THREADS_H_ */
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "threads.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
Mutex::Mutex() {
|
||||
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) {
|
||||
HANDLE thread;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ThreadBase::~ThreadBase() {
|
||||
if (running) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ThreadBase::start() {
|
||||
thread = CreateThread(NULL, 0, run_thread, rd, NULL);
|
||||
if (thread == NULL) {
|
||||
return false;
|
||||
} else {
|
||||
running = true;
|
||||
return 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, 65535, 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 if (result == WAIT_TIMEOUT) {
|
||||
return false;
|
||||
} else {
|
||||
// error
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2011 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_PLATFROM_WIN32_THREADS_H_
|
||||
#define LOVE_PLATFROM_WIN32_THREADS_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
|
||||
class Mutex {
|
||||
private:
|
||||
CRITICAL_SECTION mutex;
|
||||
Mutex(const Mutex& mutex) {}
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
class ThreadBase {
|
||||
private:
|
||||
HANDLE thread;
|
||||
ThreadBase(ThreadBase& thread) {}
|
||||
bool running;
|
||||
|
||||
static int thread_runner(void* param);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void main() = 0;
|
||||
|
||||
public:
|
||||
ThreadBase();
|
||||
virtual ~ThreadBase();
|
||||
|
||||
bool start();
|
||||
void wait();
|
||||
void kill();
|
||||
|
||||
static unsigned int threadId();
|
||||
};
|
||||
|
||||
|
||||
class Semaphore {
|
||||
private:
|
||||
Semaphore(const Semaphore& sem) {}
|
||||
HANDLE semaphore;
|
||||
unsigned int count;
|
||||
|
||||
public:
|
||||
Semaphore(unsigned int initial_value);
|
||||
~Semaphore();
|
||||
|
||||
unsigned int value();
|
||||
void post();
|
||||
bool wait(int timeout = -1);
|
||||
bool tryWait();
|
||||
};
|
||||
|
||||
|
||||
// Should conditional inherit from mutex?
|
||||
class Conditional {
|
||||
private:
|
||||
Mutex mutex;
|
||||
int waiting;
|
||||
int signals;
|
||||
Semaphore sem;
|
||||
Semaphore done;
|
||||
|
||||
public:
|
||||
Conditional();
|
||||
~Conditional();
|
||||
|
||||
void signal();
|
||||
void broadcast();
|
||||
bool wait(Mutex* cmutex, int timeout=-1);
|
||||
};
|
||||
} // namespace thread
|
||||
} // namespace love
|
||||
|
||||
#endif /* LOVE_PLATFROM_WIN32_THREADS_H_ */
|
||||
@@ -35,8 +35,6 @@ namespace
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
Thread *luax_checkthread(lua_State *L, int idx)
|
||||
{
|
||||
@@ -390,4 +388,3 @@ namespace sdl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,6 @@ namespace love
|
||||
{
|
||||
extern StringMap<Type, TYPE_MAX_ENUM> types;
|
||||
namespace thread
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
Thread *luax_checkthread(lua_State *L, int idx);
|
||||
int w_Thread_start(lua_State *L);
|
||||
@@ -49,7 +47,7 @@ namespace sdl
|
||||
int w_getThread(lua_State *L);
|
||||
|
||||
extern "C" LOVE_EXPORT int luaopen_love_thread(lua_State * L);
|
||||
} // sdl
|
||||
|
||||
} // thread
|
||||
} // love
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
**/
|
||||
|
||||
#include <common/config.h>
|
||||
#include <common/delay.h>
|
||||
|
||||
#ifdef LOVE_WINDOWS
|
||||
# include <windows.h>
|
||||
@@ -81,7 +82,7 @@ namespace sdl
|
||||
void Timer::sleep(int ms)
|
||||
{
|
||||
if(ms > 0)
|
||||
SDL_Delay(ms);
|
||||
delay(ms);
|
||||
}
|
||||
|
||||
float Timer::getDelta() const
|
||||
|
||||
Reference in New Issue
Block a user