btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $Id: event.c,v 1.3 2005/06/23 22:02:10 av1-op Exp $
 *
 * Author: Markus Stenberg <fingon@iki.fi>
 *
 *  Copyright (c) 1996 Markus Stenberg
 *  Copyright (c) 1999-2005 Kevin Stevens
 *       All rights reserved
 *
 * Created: Tue Aug 27 19:01:55 1996 fingon
 * Last modified: Tue Nov 10 16:21:43 1998 fingon
 *
 */

/* Interface for creating pretty damn nasty timed events, with
   additional load balancing in the works.

   Description of the interface:

   void muxevent_add()

   Adds a new event to occur <time> ticks from now on, which calls
   function func with the present event as parameter, and with data as
   the data (also optional type can be supplied ; just makes deletion
   of stuff of particular type far faster, and allows nice statistics)

   void muxevent_initialize()
   Initializes the event system

   void muxevent_run()
   Runs one 'tick' of events (second, 1/10sec, whatever)

   int muxevent_count_type(int type)
   int muxevent_count_type_data(int type, void *data)
   int muxevent_count_data(void *data)
   Counts pending events (count_type is fast ; count_type_data relatively
   slow and count_data a dog)
   int muxevent_last_type()
   Returns # of the last type that has been used
   int muxevent_last_type_data(int type, void *data)
   Finds the event furthest in the future and returns the difference
   in seconds to present time (or actually in event ticks)

   void muxevent_gothru_type_data(int type, void *data, void (*func)(MUXEVENT *))
   Executes the function func for every object in tye first_in_type
   queue matching type, and/or data.


*/


/* NOTE:
   This approach turns _very_ costly, if you have regularly events
   further than LOOKAHEAD_STACK_SIZE in the future
   */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <event.h>

#include "muxevent.h"
#include "create.h"
#include "debug.h"

int muxevent_tick = 0;

/* Stack of the events according to date */
static MUXEVENT **muxevent_first_in_type = NULL;

/* Whole list (dual linked) */
static MUXEVENT *muxevent_list = NULL;

/* List of 'free' events */
static MUXEVENT *muxevent_free_list = NULL;

static int last_muxevent_type = -1;
/* The main add-to-lists event handling function */

extern void prerun_event(MUXEVENT * e);
extern void postrun_event(MUXEVENT * e);

static void muxevent_delete(MUXEVENT *);

#define Zombie(e) (e->flags & FLAG_ZOMBIE)
#define LoopType(type,var) \
    for (var = muxevent_first_in_type[type] ; var ; var = var->next_in_type) \
if (!Zombie(var))

#define LoopEvent(var) \
    for (var = muxevent_list ; var ; var = var->next_in_main) \
if (!Zombie(var))

static void muxevent_wakeup(int fd, short event, void *arg) {
    MUXEVENT *e = (MUXEVENT *)arg;

    if(Zombie(e)) {
        muxevent_delete(e);
        return;
    }
    prerun_event(e);
    e->function(e);
    postrun_event(e);
    muxevent_delete(e);
}

void muxevent_add(int time, int flags, int type, void (*func) (MUXEVENT *),
        void *data, void *data2) {
    MUXEVENT *e;
    struct timeval tv;

    int i, spot;

    if (time < 1)
        time = 1;
    /* Nasty thing about the new system : we _do_ have to allocate
       muxevent_first_in_type dynamically. */
    if (type > last_muxevent_type) {
        muxevent_first_in_type =
            realloc(muxevent_first_in_type, sizeof(MUXEVENT *) * (type + 1));
        for (i = last_muxevent_type + 1; i <= type; i++)
            muxevent_first_in_type[i] = NULL;
        last_muxevent_type = type;
    }
    if (muxevent_free_list) {
        e = muxevent_free_list;
        muxevent_free_list = muxevent_free_list->next;
    } else
        Create(e, MUXEVENT, 1);

    e->flags = flags;
    e->function = func;
    e->data = data;
    e->data2 = data2;
    e->type = type;
    e->tick = muxevent_tick + time;
    e->next = NULL;


    tv.tv_sec = time;
    tv.tv_usec = 0;
    
    evtimer_set(&e->ev, muxevent_wakeup, e);
    evtimer_add(&e->ev, &tv);

    ADD_TO_BIDIR_LIST_HEAD(muxevent_list, prev_in_main, next_in_main, e);
    ADD_TO_BIDIR_LIST_HEAD(muxevent_first_in_type[type], prev_in_type,
            next_in_type, e);
}

/* Remove event */

static void muxevent_delete(MUXEVENT * e) {
    if(evtimer_pending(&e->ev, NULL)) {
        evtimer_del(&e->ev);
    }

    if (e->flags & FLAG_FREE_DATA)
        free((void *) e->data);
    if (e->flags & FLAG_FREE_DATA2)
        free((void *) e->data2);

    REMOVE_FROM_BIDIR_LIST(muxevent_list, prev_in_main, next_in_main, e);
    REMOVE_FROM_BIDIR_LIST(muxevent_first_in_type[(int) e->type],
            prev_in_type, next_in_type, e);
    ADD_TO_LIST_HEAD(muxevent_free_list, next, e);
}

/* Run the thingy */

void muxevent_run() {
    muxevent_tick += 1;
}

int muxevent_run_by_type(int type) {
    MUXEVENT *e;
    int ran = 0;

    if (type <= last_muxevent_type) {
        for (e = muxevent_first_in_type[type]; e; e = e->next_in_type) {
            if (!Zombie(e)) {
                prerun_event(e);
                e->function(e);
                postrun_event(e);
                e->flags |= FLAG_ZOMBIE;
                ran++;
            }
        }
    }
    return ran;
}

int muxevent_last_type() {
    return last_muxevent_type;
}

/* Initialize the events */

void muxevent_initialize() {
    dprintk("muxevent initializing");
}

/* Event removal functions */

void muxevent_remove_data(void *data) {
    MUXEVENT *e;

    for (e = muxevent_list; e; e = e->next_in_main)
        if (e->data == data)
            e->flags |= FLAG_ZOMBIE;
}

void muxevent_remove_type_data(int type, void *data) {
    MUXEVENT *e;

    if (type > last_muxevent_type)
        return;
    for (e = muxevent_first_in_type[type]; e; e = e->next_in_type)
        if (e->data == data)
            e->flags |= FLAG_ZOMBIE;
}

void muxevent_remove_type_data2(int type, void *data) {
    MUXEVENT *e;

    if (type > last_muxevent_type)
        return;
    for (e = muxevent_first_in_type[type]; e; e = e->next_in_type)
        if (e->data2 == data)
            e->flags |= FLAG_ZOMBIE;
}

void muxevent_remove_type_data_data(int type, void *data, void *data2) {
    MUXEVENT *e;

    if (type > last_muxevent_type)
        return;
    for (e = muxevent_first_in_type[type]; e; e = e->next_in_type)
        if (e->data == data && e->data2 == data2)
            e->flags |= FLAG_ZOMBIE;
}



/* return the args of the event */
void muxevent_get_type_data(int type, void *data, int *data2) {
    MUXEVENT *e;

    LoopType(type, e)
        if (e->data == data)
            *data2 = (int) e->data2;
}

/* All the counting / other kinds of 'useless' functions */
int muxevent_count_type(int type) {
    MUXEVENT *e;
    int count = 0;

    if (type > last_muxevent_type)
        return count;
    LoopType(type, e)
        count++;
    return count;
}


int muxevent_count_type_data(int type, void *data) {
    MUXEVENT *e;
    int count = 0;

    if (type > last_muxevent_type)
        return count;
    LoopType(type, e)
        if (e->data == data)
            count++;
    return count;
}

int muxevent_count_type_data2(int type, void *data) {
    MUXEVENT *e;
    int count = 0;

    if (type > last_muxevent_type)
        return count;
    LoopType(type, e)
        if (e->data2 == data)
            count++;
    return count;
}

int muxevent_count_type_data_data(int type, void *data, void *data2) {
    MUXEVENT *e;
    int count = 0;

    if (type > last_muxevent_type)
        return count;
    LoopType(type, e)
        if (e->data == data && e->data2 == data2)
            count++;
    return count;
}

int muxevent_count_data(int type, void *data) {
    MUXEVENT *e;
    int count = 0;

    LoopEvent(e)
        if (e->data == data)
            count++;
    return count;
}


int muxevent_count_data_data(int type, void *data, void *data2) {
    MUXEVENT *e;
    int count = 0;

    LoopEvent(e)
        if (e->data == data && e->data2 == data2)
            count++;
    return count;
}

void muxevent_gothru_type_data(int type, void *data, void (*func) (MUXEVENT *)) {
    MUXEVENT *e;

    if (type > last_muxevent_type)
        return;
    LoopType(type, e)
        if (e->data == data)
            func(e);
}

void muxevent_gothru_type(int type, void (*func) (MUXEVENT *)) {
    MUXEVENT *e;

    if (type > last_muxevent_type)
        return;
    LoopType(type, e)
        func(e);
}

int muxevent_last_type_data(int type, void *data) {
    MUXEVENT *e;
    int last = 0, t;

    if (type > last_muxevent_type)
        return last;
    LoopType(type, e)
        if (e->data == data)
            if ((t = (e->tick - muxevent_tick)) > last)
                last = t;
    return last;
}

int muxevent_first_type_data(int type, void *data) {
    MUXEVENT *e;
    int last = -1, t;

    if (type > last_muxevent_type)
        return last;
    LoopType(type, e)
        if (e->data == data)
            if ((t = (e->tick - muxevent_tick)) < last || last < 0)
                if (t > 0)
                    last = t;
    return last;
}

int muxevent_count_type_data_firstev(int type, void *data) {
    MUXEVENT *e;

    if (type > last_muxevent_type)
        return -1;
    LoopType(type, e)
        if (e->data == data)
        {
            return (int) (e->data2);
        }
    return -1;
}