event/event.c

Go to the documentation of this file.
00001 
00002 /*
00003  * $Id: event.c,v 1.3 2005/06/23 22:02:10 av1-op Exp $
00004  *
00005  * Author: Markus Stenberg <fingon@iki.fi>
00006  *
00007  *  Copyright (c) 1996 Markus Stenberg
00008  *  Copyright (c) 1999-2005 Kevin Stevens
00009  *       All rights reserved
00010  *
00011  * Created: Tue Aug 27 19:01:55 1996 fingon
00012  * Last modified: Tue Nov 10 16:21:43 1998 fingon
00013  *
00014  */
00015 
00016 /* Interface for creating pretty damn nasty timed events, with
00017    additional load balancing in the works.
00018 
00019    Description of the interface:
00020 
00021    void muxevent_add()
00022 
00023    Adds a new event to occur <time> ticks from now on, which calls
00024    function func with the present event as parameter, and with data as
00025    the data (also optional type can be supplied ; just makes deletion
00026    of stuff of particular type far faster, and allows nice statistics)
00027 
00028    void muxevent_initialize()
00029    Initializes the event system
00030 
00031    void muxevent_run()
00032    Runs one 'tick' of events (second, 1/10sec, whatever)
00033 
00034    int muxevent_count_type(int type)
00035    int muxevent_count_type_data(int type, void *data)
00036    int muxevent_count_data(void *data)
00037    Counts pending events (count_type is fast ; count_type_data relatively
00038    slow and count_data a dog)
00039    int muxevent_last_type()
00040    Returns # of the last type that has been used
00041    int muxevent_last_type_data(int type, void *data)
00042    Finds the event furthest in the future and returns the difference
00043    in seconds to present time (or actually in event ticks)
00044 
00045    void muxevent_gothru_type_data(int type, void *data, void (*func)(MUXEVENT *))
00046    Executes the function func for every object in tye first_in_type
00047    queue matching type, and/or data.
00048 
00049 
00050 */
00051 
00052 
00053 /* NOTE:
00054    This approach turns _very_ costly, if you have regularly events
00055    further than LOOKAHEAD_STACK_SIZE in the future
00056    */
00057 
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <string.h>
00061 #include <sys/time.h>
00062 #include <sys/types.h>
00063 #include <time.h>
00064 #include <event.h>
00065 
00066 #include "muxevent.h"
00067 #include "create.h"
00068 #include "debug.h"
00069 
00070 int muxevent_tick = 0;
00071 
00072 /* Stack of the events according to date */
00073 static MUXEVENT **muxevent_first_in_type = NULL;
00074 
00075 /* Whole list (dual linked) */
00076 static MUXEVENT *muxevent_list = NULL;
00077 
00078 /* List of 'free' events */
00079 static MUXEVENT *muxevent_free_list = NULL;
00080 
00081 static int last_muxevent_type = -1;
00082 /* The main add-to-lists event handling function */
00083 
00084 extern void prerun_event(MUXEVENT * e);
00085 extern void postrun_event(MUXEVENT * e);
00086 
00087 static void muxevent_delete(MUXEVENT *);
00088 
00089 #define Zombie(e) (e->flags & FLAG_ZOMBIE)
00090 #define LoopType(type,var) \
00091     for (var = muxevent_first_in_type[type] ; var ; var = var->next_in_type) \
00092 if (!Zombie(var))
00093 
00094 #define LoopEvent(var) \
00095     for (var = muxevent_list ; var ; var = var->next_in_main) \
00096 if (!Zombie(var))
00097 
00098 static void muxevent_wakeup(int fd, short event, void *arg) {
00099     MUXEVENT *e = (MUXEVENT *)arg;
00100 
00101     if(Zombie(e)) {
00102         muxevent_delete(e);
00103         return;
00104     }
00105     prerun_event(e);
00106     e->function(e);
00107     postrun_event(e);
00108     muxevent_delete(e);
00109 }
00110 
00111 void muxevent_add(int time, int flags, int type, void (*func) (MUXEVENT *),
00112         void *data, void *data2) {
00113     MUXEVENT *e = (MUXEVENT *)0xDEADBEEF;
00114     struct timeval tv = { 0, 0};
00115 
00116     int i, spot;
00117 
00118     if (time < 1)
00119         time = 1;
00120     /* Nasty thing about the new system : we _do_ have to allocate
00121        muxevent_first_in_type dynamically. */
00122     if (type > last_muxevent_type) {
00123         muxevent_first_in_type =
00124             realloc(muxevent_first_in_type, sizeof(MUXEVENT *) * (type + 1));
00125         for (i = last_muxevent_type + 1; i <= type; i++)
00126             muxevent_first_in_type[i] = NULL;
00127         last_muxevent_type = type;
00128     }
00129     if (muxevent_free_list) {
00130         e = muxevent_free_list;
00131         muxevent_free_list = muxevent_free_list->next;
00132     } else {
00133         e = malloc(sizeof(MUXEVENT));
00134         memset(e, 0, sizeof(MUXEVENT));
00135     }
00136 
00137     e->flags = flags;
00138     e->function = func;
00139     e->data = data;
00140     e->data2 = data2;
00141     e->type = type;
00142     e->tick = muxevent_tick + time;
00143     e->next = NULL;
00144 
00145 
00146     tv.tv_sec = time;
00147     tv.tv_usec = 0;
00148     
00149     evtimer_set(&e->ev, muxevent_wakeup, e);
00150     evtimer_add(&e->ev, &tv);
00151 
00152     ADD_TO_BIDIR_LIST_HEAD(muxevent_list, prev_in_main, next_in_main, e);
00153     ADD_TO_BIDIR_LIST_HEAD(muxevent_first_in_type[type], prev_in_type,
00154             next_in_type, e);
00155 }
00156 
00157 /* Remove event */
00158 
00159 static void muxevent_delete(MUXEVENT * e) {
00160     if(evtimer_pending(&e->ev, NULL)) {
00161         evtimer_del(&e->ev);
00162     }
00163 
00164     if (e->flags & FLAG_FREE_DATA)
00165         free((void *) e->data);
00166     if (e->flags & FLAG_FREE_DATA2)
00167         free((void *) e->data2);
00168 
00169     REMOVE_FROM_BIDIR_LIST(muxevent_list, prev_in_main, next_in_main, e);
00170     REMOVE_FROM_BIDIR_LIST(muxevent_first_in_type[(int) e->type],
00171             prev_in_type, next_in_type, e);
00172     ADD_TO_LIST_HEAD(muxevent_free_list, next, e);
00173 }
00174 
00175 /* Run the thingy */
00176 
00177 void muxevent_run() {
00178     muxevent_tick += 1;
00179 }
00180 
00181 int muxevent_run_by_type(int type) {
00182     MUXEVENT *e;
00183     int ran = 0;
00184 
00185     if (type <= last_muxevent_type) {
00186         for (e = muxevent_first_in_type[type]; e; e = e->next_in_type) {
00187             if (!Zombie(e)) {
00188                 prerun_event(e);
00189                 e->function(e);
00190                 postrun_event(e);
00191                 e->flags |= FLAG_ZOMBIE;
00192                 ran++;
00193             }
00194         }
00195     }
00196     return ran;
00197 }
00198 
00199 int muxevent_last_type() {
00200     return last_muxevent_type;
00201 }
00202 
00203 /* Initialize the events */
00204 
00205 void muxevent_initialize() {
00206     dprintk("muxevent initializing");
00207 }
00208 
00209 /* Event removal functions */
00210 
00211 void muxevent_remove_data(void *data) {
00212     MUXEVENT *e;
00213 
00214     for (e = muxevent_list; e; e = e->next_in_main)
00215         if (e->data == data)
00216             e->flags |= FLAG_ZOMBIE;
00217 }
00218 
00219 void muxevent_remove_type_data(int type, void *data) {
00220     MUXEVENT *e;
00221 
00222     if (type > last_muxevent_type)
00223         return;
00224     for (e = muxevent_first_in_type[type]; e; e = e->next_in_type)
00225         if (e->data == data) {
00226                 
00227             e->flags |= FLAG_ZOMBIE;
00228         }
00229 }
00230 
00231 void muxevent_remove_type_data2(int type, void *data) {
00232     MUXEVENT *e;
00233 
00234     if (type > last_muxevent_type)
00235         return;
00236     for (e = muxevent_first_in_type[type]; e; e = e->next_in_type)
00237         if (e->data2 == data)
00238             e->flags |= FLAG_ZOMBIE;
00239 }
00240 
00241 void muxevent_remove_type_data_data(int type, void *data, void *data2) {
00242     MUXEVENT *e;
00243 
00244     if (type > last_muxevent_type)
00245         return;
00246     for (e = muxevent_first_in_type[type]; e; e = e->next_in_type)
00247         if (e->data == data && e->data2 == data2)
00248             e->flags |= FLAG_ZOMBIE;
00249 }
00250 
00251 
00252 
00253 /* return the args of the event */
00254 void muxevent_get_type_data(int type, void *data, int *data2) {
00255     MUXEVENT *e;
00256 
00257     LoopType(type, e)
00258         if (e->data == data)
00259             *data2 = (int) e->data2;
00260 }
00261 
00262 /* All the counting / other kinds of 'useless' functions */
00263 int muxevent_count_type(int type) {
00264     MUXEVENT *e;
00265     int count = 0;
00266 
00267     if (type > last_muxevent_type)
00268         return count;
00269     LoopType(type, e)
00270         count++;
00271     return count;
00272 }
00273 
00274 
00275 int muxevent_count_type_data(int type, void *data) {
00276     MUXEVENT *e;
00277     int count = 0;
00278 
00279     if (type > last_muxevent_type)
00280         return count;
00281     LoopType(type, e)
00282         if (e->data == data)
00283             count++;
00284     return count;
00285 }
00286 
00287 int muxevent_count_type_data2(int type, void *data) {
00288     MUXEVENT *e;
00289     int count = 0;
00290 
00291     if (type > last_muxevent_type)
00292         return count;
00293     LoopType(type, e)
00294         if (e->data2 == data)
00295             count++;
00296     return count;
00297 }
00298 
00299 int muxevent_count_type_data_data(int type, void *data, void *data2) {
00300     MUXEVENT *e;
00301     int count = 0;
00302 
00303     if (type > last_muxevent_type)
00304         return count;
00305     LoopType(type, e)
00306         if (e->data == data && e->data2 == data2)
00307             count++;
00308     return count;
00309 }
00310 
00311 int muxevent_count_data(int type, void *data) {
00312     MUXEVENT *e;
00313     int count = 0;
00314 
00315     LoopEvent(e)
00316         if (e->data == data)
00317             count++;
00318     return count;
00319 }
00320 
00321 
00322 int muxevent_count_data_data(int type, void *data, void *data2) {
00323     MUXEVENT *e;
00324     int count = 0;
00325 
00326     LoopEvent(e)
00327         if (e->data == data && e->data2 == data2)
00328             count++;
00329     return count;
00330 }
00331 
00332 void muxevent_gothru_type_data(int type, void *data, void (*func) (MUXEVENT *)) {
00333     MUXEVENT *e;
00334 
00335     if (type > last_muxevent_type)
00336         return;
00337     LoopType(type, e)
00338         if (e->data == data)
00339             func(e);
00340 }
00341 
00342 void muxevent_gothru_type(int type, void (*func) (MUXEVENT *)) {
00343     MUXEVENT *e;
00344 
00345     if (type > last_muxevent_type)
00346         return;
00347     LoopType(type, e)
00348         func(e);
00349 }
00350 
00351 int muxevent_last_type_data(int type, void *data) {
00352     MUXEVENT *e;
00353     int last = 0, t;
00354 
00355     if (type > last_muxevent_type)
00356         return last;
00357     LoopType(type, e)
00358         if (e->data == data)
00359             if ((t = (e->tick - muxevent_tick)) > last)
00360                 last = t;
00361     return last;
00362 }
00363 
00364 int muxevent_first_type_data(int type, void *data) {
00365     MUXEVENT *e;
00366     int last = -1, t;
00367 
00368     if (type > last_muxevent_type)
00369         return last;
00370     LoopType(type, e)
00371         if (e->data == data)
00372             if ((t = (e->tick - muxevent_tick)) < last || last < 0)
00373                 if (t > 0)
00374                     last = t;
00375     return last;
00376 }
00377 
00378 int muxevent_count_type_data_firstev(int type, void *data) {
00379     MUXEVENT *e;
00380 
00381     if (type > last_muxevent_type)
00382         return -1;
00383     LoopType(type, e)
00384         if (e->data == data)
00385         {
00386             return (int) (e->data2);
00387         }
00388     return -1;
00389 }
00390 

Generated on Mon May 28 04:25:18 2007 for BattletechMUX by  doxygen 1.4.7