anaglym/anaglym.cc
Josh Holtrop 917a226e0f maintaining an event queue for passing events to the engine thread from the main SDL thread
git-svn-id: svn://anubis/anaglym/trunk@79 99a6e188-d820-4881-8870-2d33a10e2619
2009-10-14 01:20:58 +00:00

170 lines
3.5 KiB
C++

#include "Video.h"
#include "anaglym.h"
#include "Engine.h"
#include "SDL.h"
#include <stdlib.h> /* exit() */
#include <iostream>
#include <string>
#include <queue>
using namespace std;
enum EventType { EVENT_UPDATE };
typedef struct
{
EventType type;
} Event;
static void usage();
static void mainloop();
static void update();
static void addEvent(const Event & event);
static Uint32 updateCallback(Uint32 interval, void * param);
static bool lastDrawCompleted;
static bool engine_running;
static SDL_Event userEvent;
static SDL_cond * event_condition;
static SDL_mutex * event_mutex;
static SDL_mutex * event_queue_mutex;
static queue<Event> event_queue;
Uint32 g_ticks;
static void usage()
{
cerr << "Usage: anaglym [options] program.lua[c]" << endl;
exit(42);
}
static int engine_thread(void * param)
{
const char * program = (const char *) param;
if (g_engine->load(program))
{
for (;;)
{
SDL_mutexP(event_mutex);
SDL_CondWait(event_condition, event_mutex);
}
}
engine_running = false;
return 0;
}
int main(int argc, char * argv[])
{
const char * program = NULL;
for (int i = 1; i < argc; i++)
{
if (argv[i][0] != '-')
{
if (program == NULL)
{
program = argv[i];
}
else
{
cerr << "Warning: argument " << argv[i] << " ignored!" << endl;
usage();
}
}
else
{
cerr << "Warning: Unrecognized option '" << argv[i]+1
<< "'" << endl;
usage();
}
}
if (program == NULL)
{
usage();
}
lastDrawCompleted = true;
engine_running = true;
/* setup SDL update event */
userEvent.type = SDL_USEREVENT;
userEvent.user.code = 0;
event_condition = SDL_CreateCond();
event_mutex = SDL_CreateMutex();
event_queue_mutex = SDL_CreateMutex();
Video video;
#if 0
/* start in windowed mode for debugging */
video.start(0, 0, false, false);
#else
video.start();
#endif
g_engine = new Engine(argv[0]);
SDL_CreateThread(engine_thread, (void *) program);
mainloop();
SDL_DestroyCond(event_condition);
delete g_engine;
video.stop();
return 0;
}
/* called by SDL when the update timer expires */
static Uint32 updateCallback(Uint32 interval, void * param)
{
if (lastDrawCompleted)
SDL_PushEvent(&userEvent);
return interval;
}
static void mainloop()
{
SDL_Event event;
/* register a screen redrawing SDL event */
SDL_AddTimer(25, &updateCallback, NULL);
while (SDL_WaitEvent(&event))
{
if (!engine_running)
goto RET;
switch (event.type)
{
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
goto RET;
}
break;
case SDL_QUIT:
goto RET;
break;
case SDL_USEREVENT:
if (event.user.code == 0)
{
update();
}
break;
}
}
RET:
;
}
static void update()
{
Event update_event;
update_event.type = EVENT_UPDATE;
addEvent(update_event);
}
static void addEvent(const Event & event)
{
SDL_mutexP(event_queue_mutex);
event_queue.push(event);
SDL_mutexV(event_queue_mutex);
SDL_CondSignal(event_condition);
}