00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <sys/time.h>
00021 #include <sys/types.h>
00022 #include <unistd.h>
00023
00024 #include "event.h"
00025
00026 static struct event *time_event_list = NULL;
00027 static struct event *fd_event_list = NULL;
00028 static struct event *always_event_list = NULL;
00029 static int end_loop = 0;
00030
00031 int time_diff( time_ref *tr_start, time_ref *tr_end )
00032 {
00033 return ( ( tr_end->tv_sec - tr_start->tv_sec ) * 1000000
00034 + tr_end->tv_usec - tr_start->tv_usec + 500 ) / 1000;
00035 }
00036
00037 int time_ago( time_ref *tr )
00038 {
00039 struct timeval now;
00040
00041 gettimeofday( &now, NULL );
00042 return time_diff( tr, &now );
00043 }
00044
00045 void time_now( time_ref *tr )
00046 {
00047 gettimeofday( (struct timeval *)tr, NULL );
00048 }
00049
00050 void time_add( time_ref *tr, int msec )
00051 {
00052 tr->tv_sec += msec / 1000;
00053 tr->tv_usec += ( msec % 1000 ) * 1000;
00054 }
00055
00056 void time_future( time_ref *tr, int msec )
00057 {
00058 gettimeofday( tr, NULL );
00059 time_add( tr, msec );
00060 }
00061
00062 static struct event *new_event( callback f, void *d )
00063 {
00064 struct event *e;
00065
00066 e = (struct event *)malloc( sizeof( struct event ) );
00067 e->next = NULL;
00068 e->prev = NULL;
00069 e->type = 0;
00070 e->flags = 0;
00071 e->func = f;
00072 e->data = d;
00073 return e;
00074 }
00075
00076 static void strip_events( struct event **list )
00077 {
00078 struct event *e, *n;
00079
00080 for( e = *list; e; e = n )
00081 {
00082 n = e->next;
00083 if( e->flags & EVENT_F_REMOVE )
00084 {
00085 if( e->next ) e->next->prev = e->prev;
00086 if( e->prev ) e->prev->next = e->next;
00087 else *list = e->next;
00088 }
00089 }
00090 }
00091
00092 struct event *add_timer_event( int msec, unsigned int flags, callback f, void *d )
00093 {
00094 struct event *e;
00095
00096 e = new_event( f, d );
00097 e->type = EVENT_TIME;
00098 e->flags = flags;
00099 e->ev.time.ival = msec;
00100 e->next = time_event_list;
00101 if( e->next ) e->next->prev = e;
00102 time_event_list = e;
00103 time_now( &e->ev.time.fire );
00104 resched_event( e, NULL );
00105 return e;
00106 }
00107
00108 struct event *add_alarm_event( time_ref *t, unsigned int flags, callback f, void *d )
00109 {
00110 struct event *e;
00111
00112 e = new_event( f, d );
00113 e->type = EVENT_TIME;
00114 e->flags = flags | EVENT_F_ONESHOT;
00115 e->next = time_event_list;
00116 if( e->next ) e->next->prev = e;
00117 time_event_list = e;
00118 resched_event( e, t );
00119 return e;
00120 }
00121
00122 void resched_event( struct event *e, time_ref *tr )
00123 {
00124 if( tr )
00125 e->ev.time.fire = *tr;
00126 else if( e->flags & EVENT_F_ENABLED )
00127 time_add( &e->ev.time.fire, e->ev.time.ival );
00128 else
00129 time_future( &e->ev.time.fire, e->ev.time.ival );
00130
00131 e->flags &= ~EVENT_F_REMOVE;
00132 e->flags |= EVENT_F_ENABLED;
00133 }
00134
00135 struct event *add_fd_event( int fd, int write, unsigned int flags, callback f, void *d )
00136 {
00137 struct event *e;
00138
00139 e = new_event( f, d );
00140 e->type = EVENT_FD;
00141 e->flags = flags | EVENT_F_ENABLED;
00142 e->ev.fd.fd = fd;
00143 e->ev.fd.write = write;
00144 e->next = fd_event_list;
00145 if( e->next ) e->next->prev = e;
00146 fd_event_list = e;
00147 return e;
00148 }
00149
00150 struct event *add_always_event( unsigned int flags, callback f, void *d )
00151 {
00152 struct event *e;
00153
00154 e = new_event( f, d );
00155 e->type = EVENT_ALWAYS;
00156 e->flags = flags | EVENT_F_ENABLED;
00157 e->next = always_event_list;
00158 if( e->next ) e->next->prev = e;
00159 always_event_list = e;
00160 return e;
00161 }
00162
00163 void remove_event( struct event *e )
00164 {
00165 e->flags |= EVENT_F_REMOVE;
00166 e->flags &= ~EVENT_F_RUNNING;
00167 }
00168
00169 void set_event_interval( struct event *e, int msec )
00170 {
00171 e->ev.time.ival = msec;
00172 if( e->flags & EVENT_F_ENABLED ) resched_event( e, NULL );
00173 }
00174
00175 void set_event_enabled( struct event *e, int enabled )
00176 {
00177 e->flags &= ~EVENT_F_ENABLED;
00178 if( enabled ) e->flags |= EVENT_F_ENABLED;
00179 }
00180
00181 int get_event_enabled( struct event *e )
00182 {
00183 return e->flags & EVENT_F_ENABLED ? 1 : 0;
00184 }
00185
00186 void exit_event_loop(void)
00187 {
00188 end_loop = 1;
00189 }
00190
00191 void event_loop( int single )
00192 {
00193 struct timeval t, *st;
00194 struct event *e;
00195 int diff, nexttime = 0, highfd, ret;
00196 fd_set rfds, wfds;
00197
00198 end_loop = 0;
00199
00200 do {
00201 st = NULL;
00202
00203 for( e = time_event_list; e; e = e->next )
00204 if( e->flags & EVENT_F_ENABLED )
00205 {
00206 diff = -time_ago( &e->ev.time.fire );
00207 st = &t;
00208 if( diff < 5 ) diff = 0;
00209 if( ! st || diff < nexttime ) nexttime = diff;
00210 e->flags |= EVENT_F_RUNNING;
00211 } else e->flags &= ~EVENT_F_RUNNING;
00212 for( e = always_event_list; e; e = e->next )
00213 if( e->flags & EVENT_F_ENABLED )
00214 {
00215 st = &t;
00216 nexttime = 0;
00217 e->flags |= EVENT_F_RUNNING;
00218 } else e->flags &= ~EVENT_F_RUNNING;
00219 if( st )
00220 {
00221 t.tv_sec = nexttime / 1000;
00222 t.tv_usec = ( nexttime % 1000 ) * 1000;
00223 }
00224 FD_ZERO( &rfds );
00225 FD_ZERO( &wfds );
00226 highfd = -1;
00227
00228 for( e = fd_event_list; e; e = e->next )
00229 {
00230 if( e->flags & EVENT_F_ENABLED )
00231 {
00232 FD_SET( e->ev.fd.fd,
00233 e->ev.fd.write ? &wfds : &rfds );
00234 if( e->ev.fd.fd > highfd )
00235 highfd = e->ev.fd.fd;
00236 e->flags |= EVENT_F_RUNNING;
00237 } else e->flags &= ~EVENT_F_RUNNING;
00238 }
00239 ret = select( highfd + 1, &rfds, &wfds, NULL, st );
00240 for( e = time_event_list; e; e = e->next )
00241 {
00242 if( ! ( e->flags & EVENT_F_RUNNING ) ) continue;
00243 if( end_loop ) break;
00244 diff = -time_ago( &e->ev.time.fire );
00245 if( diff < 5 )
00246 {
00247 if( ! ( e->flags & EVENT_F_ONESHOT ) )
00248 resched_event( e, NULL );
00249 else e->flags |= EVENT_F_REMOVE;
00250 (*e->func)( e, e->data );
00251 }
00252 }
00253 for( e = always_event_list; e; e = e->next )
00254 {
00255 if( ! ( e->flags & EVENT_F_RUNNING ) ) continue;
00256 if( end_loop ) break;
00257 if( e->flags & EVENT_F_ONESHOT )
00258 e->flags |= EVENT_F_REMOVE;
00259 (*e->func)( e, e->data );
00260 }
00261 if( ret > 0 ) for( e = fd_event_list; e; e = e->next )
00262 {
00263 if( ! ( e->flags & EVENT_F_RUNNING ) ) continue;
00264 if( end_loop ) break;
00265 if( FD_ISSET( e->ev.fd.fd,
00266 e->ev.fd.write ? &wfds : &rfds ) )
00267 {
00268 if( e->flags & EVENT_F_ONESHOT )
00269 e->flags |= EVENT_F_REMOVE;
00270 (*e->func)( e, e->data );
00271 }
00272 }
00273 strip_events( &time_event_list );
00274 strip_events( &fd_event_list );
00275 strip_events( &always_event_list );
00276 } while( ! end_loop && ! single );
00277 }