Dual condition-variable non-hacky waiting-on-frame
Jeffrey Pfau jeffrey@endrift.com
Wed, 24 Apr 2013 02:43:55 -0700
3 files changed,
23 insertions(+),
8 deletions(-)
M
src/gba/renderers/video-software.c
→
src/gba/renderers/video-software.c
@@ -46,7 +46,8 @@ {
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 @@ bg->sy = 0;
} 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 @@ struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
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); }
M
src/gba/renderers/video-software.h
→
src/gba/renderers/video-software.h
@@ -71,7 +71,8 @@
uint16_t* row; pthread_mutex_t mutex; - pthread_cond_t cond; + pthread_cond_t upCond; + pthread_cond_t downCond; }; void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer);
M
src/main.c
→
src/main.c
@@ -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 @@ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
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) {