Add a FIFO-style interface to message queue.

Implement a virtual stderr for consoles.
This commit is contained in:
Themaister 2012-04-04 23:34:46 +02:00
parent ff7cbf5be2
commit fd44e0b9c6
4 changed files with 106 additions and 38 deletions

View File

@ -183,6 +183,7 @@ struct settings
#ifdef SSNES_CONSOLE
struct console_settings
{
msg_queue_t *stderr_queue;
#ifdef __CELLOS_LV2__
bool custom_bgm_enable;
#endif
@ -478,20 +479,35 @@ extern struct console_settings g_console;
#if defined(SSNES_CONSOLE) && defined(HAVE_LOGGER)
#include "logger_override.h"
#else
#ifdef SSNES_CONSOLE
#define SSNES_LOG_MSG_QUEUE(base, ...) do { \
char msg[512];
snprintf(msg, sizeof(msg), base ## __VA_ARGS__); \
if (g_console.stderr_queue) \
msg_queue_push_simple(g_console.stderr_queue, msg); \
} while(0)
#else
#define SSNES_LOG_MSG_QUEUE(base, ...) ((void)0)
#endif
#define SSNES_LOG(...) do { \
if (g_extern.verbose) \
fprintf(stderr, "SSNES: " __VA_ARGS__); \
fflush(stderr); \
SSNES_LOG_MSG_QUEUE("SSNES: ", __VA_ARGS__); \
} while (0)
#define SSNES_ERR(...) do { \
fprintf(stderr, "SSNES [ERROR] :: " __VA_ARGS__); \
fflush(stderr); \
SSNES_LOG_MSG_QUEUE("SSNES [ERROR]: ", __VA_ARGS__); \
} while (0)
#define SSNES_WARN(...) do { \
fprintf(stderr, "SSNES [WARN] :: " __VA_ARGS__); \
fflush(stderr); \
SSNES_LOG_MSG_QUEUE("SSNES [WARN]: ", __VA_ARGS__); \
} while (0)
#endif

114
message.c
View File

@ -38,6 +38,9 @@ struct msg_queue
msg_queue_t *msg_queue_new(size_t size)
{
if (size == 0)
return NULL;
msg_queue_t *queue = (msg_queue_t*)calloc(1, sizeof(*queue));
if (!queue)
return NULL;
@ -66,7 +69,7 @@ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned
if (queue->ptr >= queue->size)
return;
struct queue_elem *new_elem = (struct queue_elem*)calloc(1, sizeof(struct queue_elem));
struct queue_elem *new_elem = (struct queue_elem*)calloc(1, sizeof(*new_elem));
new_elem->prio = prio;
new_elem->duration = duration;
new_elem->msg = msg ? strdup(msg) : NULL;
@ -81,15 +84,50 @@ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned
if (child->prio <= parent->prio)
break;
else
{
queue->elems[tmp_ptr >> 1] = child;
queue->elems[tmp_ptr] = parent;
}
queue->elems[tmp_ptr >> 1] = child;
queue->elems[tmp_ptr] = parent;
tmp_ptr >>= 1;
}
}
void msg_queue_push_simple(msg_queue_t *queue, const char *msg)
{
if (queue->ptr >= queue->size)
{
if (queue->elems[1])
{
free(queue->elems[1]->msg);
free(queue->elems[1]);
}
queue->ptr--;
memmove(queue->elems, queue->elems + 1, queue->ptr * sizeof(struct queue_elem));
}
struct queue_elem *new_elem = (struct queue_elem*)calloc(1, sizeof(*new_elem));
new_elem->prio = 1;
new_elem->duration = 1;
new_elem->msg = msg ? strdup(msg) : NULL;
queue->elems[queue->ptr++] = new_elem;
}
const char *msg_queue_pull_simple(msg_queue_t *queue)
{
if (queue->ptr == 1)
return NULL;
free(queue->tmp_msg);
queue->tmp_msg = queue->elems[1]->msg;
queue->elems[1]->msg = NULL;
free(queue->elems[1]);
queue->ptr--;
memmove(queue->elems, queue->elems + 1, queue->ptr * sizeof(struct queue_elem));
return queue->tmp_msg;
}
void msg_queue_clear(msg_queue_t *queue)
{
for (size_t i = 1; i < queue->ptr; i++)
@ -112,48 +150,48 @@ const char *msg_queue_pull(msg_queue_t *queue)
return NULL;
struct queue_elem *front = queue->elems[1];
front->duration--;
if (front->duration > 0)
return front->msg;
else
free(queue->tmp_msg);
queue->tmp_msg = front->msg;
front->msg = NULL;
struct queue_elem *last = queue->elems[--queue->ptr];
queue->elems[1] = last;
free(front);
size_t tmp_ptr = 1;
for (;;)
{
free(queue->tmp_msg);
queue->tmp_msg = front->msg;
front->msg = NULL;
bool left = (tmp_ptr * 2 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]);
bool right = (tmp_ptr * 2 + 1 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]);
struct queue_elem *front = queue->elems[1];
struct queue_elem *last = queue->elems[--queue->ptr];
queue->elems[1] = last;
free(front);
if (!left && !right)
break;
size_t tmp_ptr = 1;
for (;;)
size_t switch_index = tmp_ptr;
if (left && !right)
switch_index <<= 1;
else if (right && !left)
switch_index += switch_index + 1;
else
{
bool left = (tmp_ptr * 2 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]);
bool right = (tmp_ptr * 2 + 1 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]);
if (!left && !right)
break;
size_t switch_index = tmp_ptr;
if (left && !right)
if (queue->elems[tmp_ptr * 2] >= queue->elems[tmp_ptr * 2 + 1])
switch_index <<= 1;
else if (right && !left)
switch_index += switch_index + 1;
else
{
if (queue->elems[tmp_ptr * 2] >= queue->elems[tmp_ptr * 2 + 1])
switch_index <<= 1;
else
switch_index += switch_index + 1;
}
struct queue_elem *parent = queue->elems[tmp_ptr];
struct queue_elem *child = queue->elems[switch_index];
queue->elems[tmp_ptr] = child;
queue->elems[switch_index] = parent;
tmp_ptr = switch_index;
switch_index += switch_index + 1;
}
return queue->tmp_msg;
struct queue_elem *parent = queue->elems[tmp_ptr];
struct queue_elem *child = queue->elems[switch_index];
queue->elems[tmp_ptr] = child;
queue->elems[switch_index] = parent;
tmp_ptr = switch_index;
}
return queue->tmp_msg;
}

View File

@ -32,6 +32,10 @@ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned
// Pulls highest prio message in queue. Returns NULL if no message in queue.
const char *msg_queue_pull(msg_queue_t *queue);
// Pushes and pulls in a FIFO fashion, duration is fixed to one frame, prio doesn't matter.
void msg_queue_push_simple(msg_queue_t *queue, const char *msg);
const char *msg_queue_pull_simple(msg_queue_t *queue);
// Clear out everything in queue.
void msg_queue_clear(msg_queue_t *queue);

10
ssnes.c
View File

@ -1196,12 +1196,22 @@ void ssnes_init_msg_queue(void)
{
if (!g_extern.msg_queue)
ssnes_assert(g_extern.msg_queue = msg_queue_new(8));
#ifdef SSNES_CONSOLE
if (!g_console.stderr_queue)
ssnes_assert(g_console.stderr_queue = msg_queue_new(256));
#endif
}
static void deinit_msg_queue(void)
{
if (g_extern.msg_queue)
msg_queue_free(g_extern.msg_queue);
#ifdef SSNES_CONSOLE
if (g_console.stderr_queue)
msg_queue_free(g_console.stderr_queue);
#endif
}
#ifdef HAVE_XML