Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126176
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/thread.cpp b/util/thread.cpp
index c9b2a070..30091f6e 100644
--- a/util/thread.cpp
+++ b/util/thread.cpp
@@ -1,210 +1,269 @@
#include "thread.h"
namespace Util{
namespace Thread{
LockObject::LockObject(){
initializeLock(&lock);
}
void LockObject::acquire() const {
/* quick hack to get around annoying constness */
acquireLock((Lock*) &lock);
}
void LockObject::release() const {
releaseLock((Lock*) &lock);
}
LockObject::~LockObject(){
destroyLock(&lock);
}
ScopedLock::ScopedLock(const LockObject & lock):
lock(lock){
lock.acquire();
}
ScopedLock::~ScopedLock(){
lock.release();
}
bool isUninitialized(Id thread){
return thread == uninitializedValue;
}
#ifdef USE_SDL
Id uninitializedValue = NULL;
void initializeLock(Lock * lock){
*lock = SDL_CreateMutex();
}
int acquireLock(Lock * lock){
return SDL_LockMutex(*lock);
}
int releaseLock(Lock * lock){
return SDL_UnlockMutex(*lock);
}
void destroyLock(Lock * lock){
SDL_DestroyMutex(*lock);
}
+/*
void initializeSemaphore(Semaphore * semaphore, unsigned int value){
*semaphore = SDL_CreateSemaphore(value);
}
void destroySemaphore(Semaphore * semaphore){
SDL_DestroySemaphore(*semaphore);
}
void semaphoreDecrease(Semaphore * semaphore){
SDL_SemWait(*semaphore);
}
void semaphoreIncrease(Semaphore * semaphore){
SDL_SemPost(*semaphore);
}
+*/
bool createThread(Id * thread, void * attributes, ThreadFunction function, void * arg){
*thread = SDL_CreateThread(function, arg);
return *thread != NULL;
}
void joinThread(Id thread){
SDL_WaitThread(thread, NULL);
}
void cancelThread(Id thread){
#ifndef PS3
SDL_KillThread(thread);
#endif
}
+#elif USE_ALLEGRO5
+Id uninitializedValue = 0;
+
+void initializeLock(Lock * lock){
+ *lock = al_create_mutex();
+}
+
+int acquireLock(Lock * lock){
+ al_lock_mutex(*lock);
+ return 0;
+}
+
+int releaseLock(Lock * lock){
+ al_unlock_mutex(*lock);
+ return 0;
+}
+
+struct AllegroThreadStuff{
+ AllegroThreadStuff(const ThreadFunction & function, void * arg):
+ function(function),
+ arg(arg){
+ }
+
+ ThreadFunction function;
+ void * arg;
+};
+
+static void * allegro_start_thread(ALLEGRO_THREAD * self, void * _stuff){
+ AllegroThreadStuff * stuff = (AllegroThreadStuff*) _stuff;
+ return stuff->function(stuff->arg);
+}
+
+bool createThread(Id * thread, void * attributes, ThreadFunction function, void * arg){
+ AllegroThreadStuff * stuff = new AllegroThreadStuff(function, arg);
+ *thread = al_create_thread(allegro_start_thread, stuff);
+ if (*thread != NULL){
+ al_start_thread(*thread);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void joinThread(Id thread){
+ al_join_thread(thread, NULL);
+}
+
+void cancelThread(Id thread){
+ al_destroy_thread(thread);
+}
+
+void destroyLock(Lock * lock){
+ al_destroy_mutex(*lock);
+}
+
#else
Id uninitializedValue = 0;
void initializeLock(Lock * lock){
pthread_mutex_init(lock, NULL);
}
int acquireLock(Lock * lock){
return pthread_mutex_lock(lock);
}
int releaseLock(Lock * lock){
return pthread_mutex_unlock(lock);
}
+#if 0
void initializeSemaphore(Semaphore * semaphore, unsigned int value){
sem_init(semaphore, 0, value);
}
void destroySemaphore(Semaphore * semaphore){
/* nothing */
}
void semaphoreDecrease(Semaphore * semaphore){
sem_wait(semaphore);
}
void semaphoreIncrease(Semaphore * semaphore){
sem_post(semaphore);
}
+#endif
bool createThread(Id * thread, void * attributes, ThreadFunction function, void * arg){
return pthread_create(thread, (pthread_attr_t*) attributes, function, arg) == 0;
}
void joinThread(Id thread){
pthread_join(thread, NULL);
}
void cancelThread(Id thread){
/* FIXME: cancel is not implemented for libogc, find another way.
* thread suspend/resume is there, though.
*/
#if !defined(WII)
pthread_cancel(thread);
#endif
}
void destroyLock(Lock * lock){
/* nothing */
}
#endif
}
WaitThread::WaitThread():
done(false){
Thread::initializeLock(&doneLock);
}
WaitThread::WaitThread(Thread::ThreadFunction thread, void * arg){
Thread::initializeLock(&doneLock);
start(thread, arg);
}
static void * do_thread(void * arg){
WaitThread * thread = (WaitThread *) arg;
thread->doRun();
return NULL;
}
void WaitThread::doRun(){
this->function(this->arg);
Thread::acquireLock(&doneLock);
this->done = true;
Thread::releaseLock(&doneLock);
}
void WaitThread::start(Thread::ThreadFunction thread, void * arg){
done = false;
this->arg = arg;
this->function = thread;
Thread::createThread(&this->thread, NULL, (Thread::ThreadFunction) do_thread, this);
}
bool WaitThread::isRunning(){
Thread::acquireLock(&doneLock);
bool what = done;
Thread::releaseLock(&doneLock);
return what;
}
void WaitThread::kill(){
Thread::cancelThread(thread);
Thread::joinThread(thread);
}
WaitThread::~WaitThread(){
/* FIXME: Should we join the thread? */
/* pthread_join(thread); */
Thread::joinThread(thread);
}
ThreadBoolean::ThreadBoolean(volatile bool & what, Thread::Lock & lock):
what(what),
lock(lock){
}
bool ThreadBoolean::get(){
Thread::acquireLock(&lock);
bool b = what;
Thread::releaseLock(&lock);
return b;
}
void ThreadBoolean::set(bool value){
Thread::acquireLock(&lock);
what = value;
Thread::releaseLock(&lock);
}
}
diff --git a/util/thread.h b/util/thread.h
index 12a90c55..bba244d6 100644
--- a/util/thread.h
+++ b/util/thread.h
@@ -1,216 +1,230 @@
#ifndef _paintown_thread_h
#define _paintown_thread_h
#ifdef USE_SDL
#include <SDL_thread.h>
#include <SDL_mutex.h>
+#elif USE_ALLEGRO5
+#include <allegro5/allegro5.h>
#else
#include <pthread.h>
-#include <semaphore.h>
+// #include <semaphore.h>
#endif
#include "exceptions/exception.h"
#include "load_exception.h"
#include "token_exception.h"
#include "mugen/exception.h"
#include "debug.h"
namespace Util{
/* Either uses pthreads or SDL_thread */
namespace Thread{
#ifdef USE_SDL
typedef SDL_mutex* Lock;
typedef SDL_Thread* Id;
typedef int (*ThreadFunction)(void*);
- typedef SDL_semaphore* Semaphore;
+ // typedef SDL_semaphore* Semaphore;
+#elif USE_ALLEGRO5
+ typedef ALLEGRO_MUTEX* Lock;
+ typedef ALLEGRO_THREAD* Id;
+ typedef void * (*ThreadFunction)(void*);
+ // typedef SDL_semaphore* Semaphore;
#else
typedef pthread_mutex_t Lock;
typedef pthread_t Id;
- typedef sem_t Semaphore;
+ // typedef sem_t Semaphore;
typedef void * (*ThreadFunction)(void*);
#endif
extern Id uninitializedValue;
bool isUninitialized(Id thread);
void initializeLock(Lock * lock);
+ /*
void initializeSemaphore(Semaphore * semaphore, unsigned int value);
void destroySemaphore(Semaphore * semaphore);
void semaphoreDecrease(Semaphore * semaphore);
void semaphoreIncrease(Semaphore * semaphore);
+ */
int acquireLock(Lock * lock);
int releaseLock(Lock * lock);
void destroyLock(Lock * lock);
bool createThread(Id * thread, void * attributes, ThreadFunction function, void * arg);
void joinThread(Id thread);
void cancelThread(Id thread);
/* wraps a Lock in a c++ class */
class LockObject{
public:
LockObject();
void acquire() const;
void release() const;
virtual ~LockObject();
Lock lock;
};
/* acquires/releases the lock in RAII fashion */
class ScopedLock{
public:
ScopedLock(const LockObject & lock);
~ScopedLock();
private:
const LockObject & lock;
};
}
class WaitThread{
public:
/* does not start a new thread yet */
WaitThread();
/* starts a thread */
WaitThread(Thread::ThreadFunction thread, void * arg);
/* starts a thread */
void start(Thread::ThreadFunction thread, void * arg);
bool isRunning();
void kill();
virtual ~WaitThread();
public:
/* actually runs the thread */
void doRun();
protected:
Thread::Lock doneLock;
Thread::Id thread;
volatile bool done;
void * arg;
Thread::ThreadFunction function;
};
/* wraps a boolean with lock/unlock while checking/setting it */
class ThreadBoolean{
public:
ThreadBoolean(volatile bool & what, Thread::Lock & lock);
bool get();
void set(bool value);
protected:
volatile bool & what;
Thread::Lock & lock;
};
/* Computes stuff in a separate thread and gives it back when you ask for it.
* As soon as the future is created a thread will start executing and compute
* whatever it is that the class is supposed to do. You can then call `get'
* on the future object to get the result. If the thread is still executing
* then `get' will block until the future completes. If the future has already
* completed then `get' will return immediately with the computed value.
* The use case is computing something that has to be used later:
* Future future; // might take a while to compute
* do_stuff_that_takes_a_while(); // future might finish sometime in here
* Object o = future.get(); // future is already done
*
* TODO: handle exceptions
*/
template<class X>
class Future{
protected:
/* WARNING: hack to find out the type of the exception */
/*
enum ExceptionType{
None,
Load,
Token,
Base,
Mugen
};
*/
public:
Future():
thing(0),
thread(Thread::uninitializedValue),
exception(NULL){
/* future will increase the count */
- Thread::initializeSemaphore(&future, 0);
+ // Thread::initializeSemaphore(&future, 0);
+ // future.acquire();
}
virtual ~Future(){
if (Thread::isUninitialized(thread)){
Thread::joinThread(thread);
}
- Thread::destroySemaphore(&future);
+ // Thread::destroySemaphore(&future);
delete exception;
}
virtual X get(){
X out;
Exception::Base * failed = NULL;
- Thread::semaphoreDecrease(&future);
+ future.acquire();
+ // Thread::semaphoreDecrease(&future);
if (exception != NULL){
failed = exception;
// exception->throwSelf();
}
out = thing;
- Thread::semaphoreIncrease(&future);
+ // Thread::semaphoreIncrease(&future);
+ future.release();
if (failed){
failed->throwSelf();
}
return out;
}
virtual void start(){
if (!Thread::createThread(&thread, NULL, (Thread::ThreadFunction) runit, this)){
Global::debug(0) << "Could not create future thread. Blocking until its done" << std::endl;
runit(this);
// throw Exception::Base(__FILE__, __LINE__);
}
}
protected:
static void * runit(void * arg){
Future<X> * me = (Future<X>*) arg;
+ me->future.acquire();
try{
me->compute();
} catch (const LoadException & load){
me->exception = new LoadException(load);
} catch (const TokenException & t){
me->exception = new TokenException(t);
} catch (const MugenException & m){
me->exception = new MugenException(m);
} catch (const Exception::Base & base){
me->exception = new Exception::Base(base);
}
- Thread::semaphoreIncrease(&me->future);
+ me->future.release();
+ // Thread::semaphoreIncrease(&me->future);
return NULL;
}
virtual void set(X x){
this->thing = x;
}
virtual void compute() = 0;
X thing;
Thread::Id thread;
- Thread::Semaphore future;
+ Thread::LockObject future;
/* if any exceptions occur, throw them from `get' */
Exception::Base * exception;
};
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:51 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68546
Default Alt Text
(11 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline