gnuboy-for-dfi/sys/thinlib/lib/tl_event.c

141 lines
2.6 KiB
C

/*
** thinlib (c) 2001 Matthew Conte (matt@conte.com)
**
**
** tl_event.c
**
** event handling routines
**
** $Id: $
*/
#include "tl_types.h"
#include "tl_event.h"
#include "tl_djgpp.h"
/* maximum of 8 event handling callbacks */
#define MAX_CALLBACKS 8
#define EVENT_QUEUE_MAX 256
#define EVENT_QUEUE_MASK (EVENT_QUEUE_MAX - 1)
#define EVENT_QUEUE_EMPTY (event_queue.head == event_queue.tail)
typedef struct event_queue_s
{
int head;
int tail;
thin_event_t event[EVENT_QUEUE_MAX];
} event_queue_t;
static event_queue_t event_queue;
static event_callback_t event_callback[MAX_CALLBACKS];
/* add an event. */
void thin_event_add(thin_event_t *event)
{
event_queue.event[event_queue.head] = *event;
event_queue.head = (event_queue.head + 1) & EVENT_QUEUE_MASK;
}
THIN_LOCKED_FUNC(thin_event_add)
/* get an event from the event queue. returns 0 if no events. */
int thin_event_get(thin_event_t *event)
{
if (EVENT_QUEUE_EMPTY)
{
event->type = THIN_NOEVENT;
return 0;
}
*event = event_queue.event[event_queue.tail];
event_queue.tail = (event_queue.tail + 1) & EVENT_QUEUE_MASK;
return 1;
}
/* gather up all pollable events */
void thin_event_gather(void)
{
int i;
for (i = 0; i < MAX_CALLBACKS; i++)
{
if (NULL == event_callback[i])
return;
event_callback[i]();
}
}
/* return an ID of an event callback */
event_id thin_event_add_callback(event_callback_t callback)
{
event_id id;
for (id = 0; id < MAX_CALLBACKS; id++)
{
if (NULL == event_callback[id])
break;
}
/* no event callbacks available */
if (id == MAX_CALLBACKS)
return (event_id) -1;
event_callback[id] = callback;
return id;
}
/* remove an event callback */
void thin_event_remove_callback(event_id id)
{
THIN_ASSERT(id >= 0 && id < MAX_CALLBACKS);
if (id < 0 || id >= MAX_CALLBACKS)
return;
THIN_ASSERT(NULL != event_callback[id]);
event_callback[id] = NULL;
/* move all other callbacks down */
for (; id < MAX_CALLBACKS - 1; id++)
{
event_callback[id] = event_callback[id + 1];
event_callback[id + 1] = NULL;
}
}
/* set up the event handling system */
void thin_event_init(void)
{
int i;
/* some modules call thin_event_add from an ISR, so we must
** lock everythig that is touched within that function, as
** well as the code itself.
*/
THIN_LOCK_FUNC(thin_event_add);
THIN_LOCK_VAR(event_queue);
for (i = 0; i < MAX_CALLBACKS; i++)
event_callback[i] = NULL;
event_queue.head = event_queue.tail = 0;
}
/*
** $Log: $
*/