Skip to content

Instantly share code, notes, and snippets.

@flibitijibibo
Last active April 11, 2018 18:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flibitijibibo/2dcc0989e5dbc290bd5b1749457738a6 to your computer and use it in GitHub Desktop.
Save flibitijibibo/2dcc0989e5dbc290bd5b1749457738a6 to your computer and use it in GitHub Desktop.
I needed an equivalent to Win32's Event object, so here's an SDL version. Probably isn't good.
/* SDL-based Event Object Copycat
* Written by Ethan "flibitijibibo" Lee
*
* Released under public domain.
* No warranty implied; use at your own risk.
*/
#include <SDL2/SDL.h>
typedef struct EventObject EventObject;
EventObject* EventObject_Create(Uint8 manual, Uint8 initial);
void EventObject_Destroy(EventObject *obj);
Uint8 EventObject_Set(EventObject *obj);
Uint8 EventObject_Reset(EventObject *obj);
Uint8 EventObject_Wait(EventObject *obj, int ms);
#ifdef EVENTOBJECT_IMPL /* Define this in EXACTLY ONE FILE that includes this */
struct EventObject
{
SDL_cond *cond;
SDL_mutex *mutex;
Uint8 manual;
Uint8 value;
Uint8 threads;
};
EventObject* EventObject_Create(Uint8 manual, Uint8 initial)
{
EventObject *obj = (EventObject*) SDL_malloc(sizeof(EventObject));
obj->mutex = SDL_CreateMutex();
obj->cond = SDL_CreateCond();
obj->manual = manual;
obj->value = (initial > 0) ? 0xFF : 0;
obj->threads = 0;
return obj;
}
void EventObject_Destroy(EventObject *obj)
{
/* Signal all remaining threads */
SDL_LockMutex(obj->mutex);
obj->value = 0xFF;
SDL_CondBroadcast(obj->cond);
/* Constantly lock/unlock to get threads outta here */
while (obj->threads > 0)
{
SDL_UnlockMutex(obj->mutex);
SDL_LockMutex(obj->mutex);
}
/* Destroy, finally. */
SDL_DestroyCond(obj->cond);
SDL_UnlockMutex(obj->mutex);
SDL_DestroyMutex(obj->mutex);
SDL_free(obj);
}
Uint8 EventObject_Set(EventObject *obj)
{
SDL_LockMutex(obj->mutex);
if (obj->manual)
{
/* For manual events, signal all threads */
obj->value = 0xFF;
SDL_CondBroadcast(obj->cond);
}
else
{
/* For auto events, only give one thread a signal */
obj->value += 1;
SDL_CondSignal(obj->cond);
}
SDL_UnlockMutex(obj->mutex);
return 1;
}
Uint8 EventObject_Reset(EventObject *obj)
{
SDL_LockMutex(obj->mutex);
obj->value = 0;
SDL_UnlockMutex(obj->mutex);
return 1;
}
Uint8 EventObject_Wait(EventObject *obj, int ms)
{
SDL_LockMutex(obj->mutex);
obj->threads += 1;
/* Initial check to see if we're already signaled */
if (obj->value == 0xFF)
{
obj->threads -= 1;
SDL_UnlockMutex(obj->mutex);
return 1;
}
if (obj->value > 0)
{
obj->value -= 1;
obj->threads -= 1;
SDL_UnlockMutex(obj->mutex);
return 1;
}
/* Wait... */
SDL_CondWaitTimeout(
obj->cond,
obj->mutex,
ms < 0 ? SDL_MUTEX_MAXWAIT : ms
);
/* Check for signal one last time... */
if (obj->value == 0xFF)
{
obj->threads -= 1;
SDL_UnlockMutex(obj->mutex);
return 1;
}
if (obj->value > 0)
{
obj->value -= 1;
obj->threads -= 1;
SDL_UnlockMutex(obj->mutex);
return 1;
}
obj->threads -= 1;
SDL_UnlockMutex(obj->mutex);
return 0; /* Timed out. If not, what the hell? */
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment