Dual condition-variable non-hacky waiting-on-frame

This commit is contained in:
Jeffrey Pfau 2013-04-24 02:43:55 -07:00
parent 5122a236e0
commit 00dd5bdaa8
3 changed files with 23 additions and 8 deletions

View File

@ -46,7 +46,8 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
renderer->mutex = mutex;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
renderer->cond = cond;
renderer->upCond = cond;
renderer->downCond = cond;
}
}
@ -93,14 +94,16 @@ static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) {
}
pthread_mutex_init(&softwareRenderer->mutex, 0);
pthread_cond_init(&softwareRenderer->cond, 0);
pthread_cond_init(&softwareRenderer->upCond, 0);
pthread_cond_init(&softwareRenderer->downCond, 0);
}
static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
pthread_mutex_destroy(&softwareRenderer->mutex);
pthread_cond_destroy(&softwareRenderer->cond);
pthread_cond_destroy(&softwareRenderer->upCond);
pthread_cond_destroy(&softwareRenderer->downCond);
}
static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
@ -210,8 +213,9 @@ static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* rendere
pthread_mutex_lock(&softwareRenderer->mutex);
renderer->framesPending++;
pthread_cond_broadcast(&softwareRenderer->upCond);
if (!renderer->turbo) {
pthread_cond_wait(&softwareRenderer->cond, &softwareRenderer->mutex);
pthread_cond_wait(&softwareRenderer->downCond, &softwareRenderer->mutex);
}
pthread_mutex_unlock(&softwareRenderer->mutex);
}

View File

@ -71,7 +71,8 @@ struct GBAVideoSoftwareRenderer {
uint16_t* row;
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_cond_t upCond;
pthread_cond_t downCond;
};
void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer);

View File

@ -9,6 +9,7 @@
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
struct GLSoftwareRenderer {
@ -118,12 +119,21 @@ static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer*
SDL_GL_SwapBuffers();
pthread_mutex_lock(&renderer->d.mutex);
pthread_cond_broadcast(&renderer->d.cond);
pthread_cond_broadcast(&renderer->d.downCond);
pthread_mutex_unlock(&renderer->d.mutex);
} else {
while (!renderer->d.d.framesPending) {
struct timeval tv;
struct timespec ts;
gettimeofday(&tv, 0);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000 + 800000;
int err = pthread_cond_timedwait(&renderer->d.upCond, &renderer->d.mutex, &ts);
if (err == ETIMEDOUT) {
break;
}
}
pthread_mutex_unlock(&renderer->d.mutex);
// We have no frame, let's just wait a sec to see if we get one.
usleep(500);
}
while (SDL_PollEvent(&event)) {
switch (event.type) {