#include "itc.h" void itc_chan_create(itc_chan *chan) { memset(chan, 0, sizeof(itc_chan)); chan->mutex = SDL_CreateMutex(); assert(chan->mutex); chan->sem = SDL_CreateSemaphore(0); assert(chan->sem); } void itc_chan_destroy(itc_chan *chan) { // todo: free queue SDL_DestroySemaphore(chan->sem); SDL_DestroyMutex(chan->mutex); } void itc_chan_push(itc_chan *chan, int number, void *data) { itc_message *msg; msg = calloc(1, sizeof(itc_message)); assert(msg); msg->number = number; msg->data = data; SDL_LockMutex(chan->mutex); if (!chan->oldest) { chan->oldest = msg; chan->newest = msg; } else { /* * head <---> ... <---> tail * */ chan->newest->newer = msg; msg->older = chan->newest; chan->newest = msg; } SDL_SemPost(chan->sem); SDL_UnlockMutex(chan->mutex); } int itc_chan_pop(itc_chan *chan, int *number, void **data) { itc_message *msg; SDL_LockMutex(chan->mutex); if (!chan->oldest) { SDL_UnlockMutex(chan->mutex); return 1; } msg = chan->oldest; if (msg->newer) { msg->newer->older = NULL; chan->oldest = msg->newer; } else { chan->newest = NULL; chan->oldest = NULL; } SDL_SemWait(chan->sem); // should be instant SDL_UnlockMutex(chan->mutex); *number = msg->number; *data = msg->data; free(msg); return 0; } int itc_chan_pop_block(itc_chan *chan, int *number, void **data) { itc_message *msg; SDL_SemWait(chan->sem); SDL_LockMutex(chan->mutex); if (!chan->oldest) { SDL_UnlockMutex(chan->mutex); return 1; } msg = chan->oldest; if (msg->newer) { msg->newer->older = NULL; chan->oldest = msg->newer; } else { chan->newest = NULL; chan->oldest = NULL; } SDL_UnlockMutex(chan->mutex); *number = msg->number; *data = msg->data; free(msg); return 0; }