mirror of
https://github.com/tbamud/tbamud.git
synced 2026-02-19 10:01:45 +01:00
Setting up 3.5.0 as trunk
This commit is contained in:
295
src/dg_event.c
Normal file
295
src/dg_event.c
Normal file
@@ -0,0 +1,295 @@
|
||||
/**************************************************************************
|
||||
* File: dg_event.c *
|
||||
* *
|
||||
* Usage: This file contains a simplified event system to allow *
|
||||
* DG Script triggers to use the "wait" command, causing a delay in the *
|
||||
* middle of a script. *
|
||||
* *
|
||||
* By: Mark A. Heilpern (Sammy @ eQuoria MUD equoria.com:4000) *
|
||||
* *
|
||||
* As of dg scripts pl 8 this includes the 'FULL' DG event package. * *
|
||||
* This file includes the file queue.c, which handles the priority queues.* *
|
||||
* Thomas Arp - Welcor - 2002 *
|
||||
* *
|
||||
* $Author: Mark A. Heilpern/egreen/Welcor $ *
|
||||
* $Date: 2004/10/11 12:07:00$ *
|
||||
* $Revision: 1.0.14 $ *
|
||||
**************************************************************************/
|
||||
/*
|
||||
* dg_event.c: This file contains a simplified event system to allow
|
||||
* DG Script triggers to use the "wait" command, causing a delay in the
|
||||
* middle of a script.
|
||||
*
|
||||
* By: Mark A. Heilpern (Sammy @ eQuoria MUD equoria.com:4000)
|
||||
*
|
||||
* As of dg scripts pl 8 this includes the 'FULL' DG event package.
|
||||
* This file includes the file queue.c, which handles the priority queues.
|
||||
* Thomas Arp - Welcor - 2002
|
||||
*
|
||||
*/
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
#include "structs.h"
|
||||
#include "db.h"
|
||||
#include "utils.h"
|
||||
#include "dg_event.h"
|
||||
#include "constants.h"
|
||||
|
||||
struct queue *event_q; /* the event queue */
|
||||
|
||||
extern long pulse;
|
||||
|
||||
/* initializes the event queue */
|
||||
void event_init(void)
|
||||
{
|
||||
event_q = queue_init();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Add an event to the current list
|
||||
*/
|
||||
/* creates an event and returns it */
|
||||
struct event *event_create(EVENTFUNC(*func), void *event_obj, long when)
|
||||
{
|
||||
struct event *new_event;
|
||||
|
||||
if (when < 1) /* make sure its in the future */
|
||||
when = 1;
|
||||
|
||||
CREATE(new_event, struct event, 1);
|
||||
new_event->func = func;
|
||||
new_event->event_obj = event_obj;
|
||||
new_event->q_el = queue_enq(event_q, new_event, when + pulse);
|
||||
|
||||
return new_event;
|
||||
}
|
||||
|
||||
|
||||
/* removes the event from the system */
|
||||
void event_cancel(struct event *event)
|
||||
{
|
||||
if (!event) {
|
||||
log("SYSERR: Attempted to cancel a NULL event");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event->q_el) {
|
||||
log("SYSERR: Attempted to cancel a non-NULL unqueued event, freeing anyway");
|
||||
} else
|
||||
queue_deq(event_q, event->q_el);
|
||||
|
||||
if (event->event_obj)
|
||||
free(event->event_obj);
|
||||
free(event);
|
||||
}
|
||||
|
||||
|
||||
/* Process any events whose time has come. */
|
||||
void event_process(void)
|
||||
{
|
||||
struct event *the_event;
|
||||
long new_time;
|
||||
|
||||
while ((long) pulse >= queue_key(event_q)) {
|
||||
if (!(the_event = (struct event *) queue_head(event_q))) {
|
||||
log("SYSERR: Attempt to get a NULL event");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the_event->q_el to NULL so that any functions called beneath
|
||||
** event_process can tell if they're being called beneath the actual
|
||||
** event function.
|
||||
*/
|
||||
the_event->q_el = NULL;
|
||||
|
||||
/* call event func, reenqueue event if retval > 0 */
|
||||
if ((new_time = (the_event->func)(the_event->event_obj)) > 0)
|
||||
the_event->q_el = queue_enq(event_q, the_event, new_time + pulse);
|
||||
else
|
||||
free(the_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* returns the time remaining before the event */
|
||||
long event_time(struct event *event)
|
||||
{
|
||||
long when;
|
||||
|
||||
when = queue_elmt_key(event->q_el);
|
||||
|
||||
return (when - pulse);
|
||||
}
|
||||
|
||||
|
||||
/* frees all events in the queue */
|
||||
void event_free_all(void)
|
||||
{
|
||||
struct event *the_event;
|
||||
|
||||
while ((the_event = (struct event *) queue_head(event_q))) {
|
||||
if (the_event->event_obj)
|
||||
free(the_event->event_obj);
|
||||
free(the_event);
|
||||
}
|
||||
|
||||
queue_free(event_q);
|
||||
}
|
||||
|
||||
/* boolean function to tell whether an event is queued or not */
|
||||
int event_is_queued(struct event *event)
|
||||
{
|
||||
if (event->q_el)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* File: queue.c *
|
||||
* *
|
||||
* Usage: generic queue functions for building and using a priority queue *
|
||||
* *
|
||||
************************************************************************ */
|
||||
|
||||
/* returns a new, initialized queue */
|
||||
struct queue *queue_init(void)
|
||||
{
|
||||
struct queue *q;
|
||||
|
||||
CREATE(q, struct queue, 1);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
/* add data into the priority queue q with key */
|
||||
struct q_element *queue_enq(struct queue *q, void *data, long key)
|
||||
{
|
||||
struct q_element *qe, *i;
|
||||
int bucket;
|
||||
|
||||
CREATE(qe, struct q_element, 1);
|
||||
qe->data = data;
|
||||
qe->key = key;
|
||||
|
||||
bucket = key % NUM_EVENT_QUEUES; /* which queue does this go in */
|
||||
|
||||
if (!q->head[bucket]) { /* queue is empty */
|
||||
q->head[bucket] = qe;
|
||||
q->tail[bucket] = qe;
|
||||
}
|
||||
|
||||
else {
|
||||
for (i = q->tail[bucket]; i; i = i->prev) {
|
||||
|
||||
if (i->key < key) { /* found insertion point */
|
||||
if (i == q->tail[bucket])
|
||||
q->tail[bucket] = qe;
|
||||
else {
|
||||
qe->next = i->next;
|
||||
i->next->prev = qe;
|
||||
}
|
||||
|
||||
qe->prev = i;
|
||||
i->next = qe;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == NULL) { /* insertion point is front of list */
|
||||
qe->next = q->head[bucket];
|
||||
q->head[bucket] = qe;
|
||||
qe->next->prev = qe;
|
||||
}
|
||||
}
|
||||
|
||||
return qe;
|
||||
}
|
||||
|
||||
|
||||
/* remove queue element qe from the priority queue q */
|
||||
void queue_deq(struct queue *q, struct q_element *qe)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(qe);
|
||||
|
||||
i = qe->key % NUM_EVENT_QUEUES;
|
||||
|
||||
if (qe->prev == NULL)
|
||||
q->head[i] = qe->next;
|
||||
else
|
||||
qe->prev->next = qe->next;
|
||||
|
||||
if (qe->next == NULL)
|
||||
q->tail[i] = qe->prev;
|
||||
else
|
||||
qe->next->prev = qe->prev;
|
||||
|
||||
free(qe);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* removes and returns the data of the
|
||||
* first element of the priority queue q
|
||||
*/
|
||||
void *queue_head(struct queue *q)
|
||||
{
|
||||
void *data;
|
||||
int i;
|
||||
|
||||
i = pulse % NUM_EVENT_QUEUES;
|
||||
|
||||
if (!q->head[i])
|
||||
return NULL;
|
||||
|
||||
data = q->head[i]->data;
|
||||
queue_deq(q, q->head[i]);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* returns the key of the head element of the priority queue
|
||||
* if q is NULL, then return the largest unsigned number
|
||||
*/
|
||||
long queue_key(struct queue *q)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = pulse % NUM_EVENT_QUEUES;
|
||||
|
||||
if (q->head[i])
|
||||
return q->head[i]->key;
|
||||
else
|
||||
return LONG_MAX;
|
||||
}
|
||||
|
||||
|
||||
/* returns the key of queue element qe */
|
||||
long queue_elmt_key(struct q_element *qe)
|
||||
{
|
||||
return qe->key;
|
||||
}
|
||||
|
||||
|
||||
/* free q and contents */
|
||||
void queue_free(struct queue *q)
|
||||
{
|
||||
int i;
|
||||
struct q_element *qe, *next_qe;
|
||||
|
||||
for (i = 0; i < NUM_EVENT_QUEUES; i++)
|
||||
for (qe = q->head[i]; qe; qe = next_qe) {
|
||||
next_qe = qe->next;
|
||||
free(qe);
|
||||
}
|
||||
|
||||
free(q);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user