- Timestamp:
- Jun 22, 2011, 3:45:52 PM (13 years ago)
- Parents:
- b343c2c (diff), 6376af1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
select.c
r44976fe r84a071f 2 2 3 3 static GMainLoop *loop = NULL; 4 static GMainContext *main_context;5 static int dispatch_active = 0;6 7 static GSource *owl_timer_source;8 static GSource *owl_io_dispatch_source;9 10 static int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2) {11 return t1->time - t2->time;12 }13 14 owl_timer *owl_select_add_timer(const char* name, int after, int interval, void (*cb)(owl_timer *, void *), void (*destroy)(owl_timer*), void *data)15 {16 owl_timer *t = g_new(owl_timer, 1);17 GList **timers = owl_global_get_timerlist(&g);18 19 t->time = time(NULL) + after;20 t->interval = interval;21 t->callback = cb;22 t->destroy = destroy;23 t->data = data;24 t->name = name ? g_strdup(name) : NULL;25 26 *timers = g_list_insert_sorted(*timers, t,27 (GCompareFunc)_owl_select_timer_cmp);28 return t;29 }30 31 void owl_select_remove_timer(owl_timer *t)32 {33 GList **timers = owl_global_get_timerlist(&g);34 if (t && g_list_find(*timers, t)) {35 *timers = g_list_remove(*timers, t);36 if(t->destroy) {37 t->destroy(t);38 }39 g_free(t->name);40 g_free(t);41 }42 }43 44 static gboolean owl_timer_prepare(GSource *source, int *timeout) {45 GList **timers = owl_global_get_timerlist(&g);46 GTimeVal now;47 48 /* TODO: In the far /far/ future, g_source_get_time is what the cool49 * kids use to get system monotonic time. */50 g_source_get_current_time(source, &now);51 52 /* FIXME: bother with millisecond accuracy now that we can? */53 if (*timers) {54 owl_timer *t = (*timers)->data;55 *timeout = t->time - now.tv_sec;56 if (*timeout <= 0) {57 *timeout = 0;58 return TRUE;59 }60 if (*timeout > 60 * 1000)61 *timeout = 60 * 1000;62 } else {63 *timeout = 60 * 1000;64 }65 return FALSE;66 }67 68 static gboolean owl_timer_check(GSource *source) {69 GList **timers = owl_global_get_timerlist(&g);70 GTimeVal now;71 72 /* TODO: In the far /far/ future, g_source_get_time is what the cool73 * kids use to get system monotonic time. */74 g_source_get_current_time(source, &now);75 76 /* FIXME: bother with millisecond accuracy now that we can? */77 if (*timers) {78 owl_timer *t = (*timers)->data;79 return t->time >= now.tv_sec;80 }81 return FALSE;82 }83 84 85 static gboolean owl_timer_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {86 GList **timers = owl_global_get_timerlist(&g);87 GTimeVal now;88 89 /* TODO: In the far /far/ future, g_source_get_time is what the cool90 * kids use to get system monotonic time. */91 g_source_get_current_time(source, &now);92 93 /* FIXME: bother with millisecond accuracy now that we can? */94 while(*timers) {95 owl_timer *t = (*timers)->data;96 int remove = 0;97 98 if(t->time > now.tv_sec)99 break;100 101 /* Reschedule if appropriate */102 if(t->interval > 0) {103 t->time = now.tv_sec + t->interval;104 *timers = g_list_remove(*timers, t);105 *timers = g_list_insert_sorted(*timers, t,106 (GCompareFunc)_owl_select_timer_cmp);107 } else {108 remove = 1;109 }110 111 /* Do the callback */112 t->callback(t, t->data);113 if(remove) {114 owl_select_remove_timer(t);115 }116 }117 return TRUE;118 }119 120 static GSourceFuncs owl_timer_funcs = {121 owl_timer_prepare,122 owl_timer_check,123 owl_timer_dispatch,124 NULL125 };126 127 /* Returns the valid owl_io_dispatch for a given file descriptor. */128 static owl_io_dispatch *owl_select_find_valid_io_dispatch_by_fd(const int fd)129 {130 int i, len;131 const owl_list *dl;132 owl_io_dispatch *d;133 dl = owl_global_get_io_dispatch_list(&g);134 len = owl_list_get_size(dl);135 for(i = 0; i < len; i++) {136 d = owl_list_get_element(dl, i);137 if (d->fd == fd && d->valid) return d;138 }139 return NULL;140 }141 142 static int owl_select_find_io_dispatch(const owl_io_dispatch *in)143 {144 int i, len;145 const owl_list *dl;146 147 if (in != NULL) {148 dl = owl_global_get_io_dispatch_list(&g);149 len = owl_list_get_size(dl);150 for(i = 0; i < len; i++) {151 const owl_io_dispatch *d = owl_list_get_element(dl, i);152 if (d == in) return i;153 }154 }155 return -1;156 }157 158 static void owl_select_invalidate_io_dispatch(owl_io_dispatch *d)159 {160 if (d == NULL || !d->valid)161 return;162 d->valid = false;163 g_source_remove_poll(owl_io_dispatch_source, &d->pollfd);164 }165 166 void owl_select_remove_io_dispatch(const owl_io_dispatch *in)167 {168 int elt;169 if (in != NULL) {170 elt = owl_select_find_io_dispatch(in);171 if (elt != -1) {172 owl_list *dl = owl_global_get_io_dispatch_list(&g);173 owl_io_dispatch *d = owl_list_get_element(dl, elt);174 if (dispatch_active)175 d->needs_gc = 1;176 else {177 owl_select_invalidate_io_dispatch(d);178 owl_list_remove_element(dl, elt);179 if (d->destroy)180 d->destroy(d);181 g_free(d);182 }183 }184 }185 }186 187 static void owl_select_io_dispatch_gc(void)188 {189 int i;190 owl_list *dl;191 192 dl = owl_global_get_io_dispatch_list(&g);193 /*194 * Count down so we aren't set off by removing items from the list195 * during the iteration.196 */197 for(i = owl_list_get_size(dl) - 1; i >= 0; i--) {198 owl_io_dispatch *d = owl_list_get_element(dl, i);199 if(d->needs_gc) {200 owl_select_remove_io_dispatch(d);201 }202 }203 }204 205 /* Each FD may have at most one valid dispatcher.206 * If a new dispatch is added for an FD, the old one is removed.207 * mode determines what types of events are watched for, and may be any combination of:208 * OWL_IO_READ, OWL_IO_WRITE, OWL_IO_EXCEPT209 */210 const owl_io_dispatch *owl_select_add_io_dispatch(int fd, int mode, void (*cb)(const owl_io_dispatch *, void *), void (*destroy)(const owl_io_dispatch *), void *data)211 {212 owl_io_dispatch *d = g_new(owl_io_dispatch, 1);213 owl_list *dl = owl_global_get_io_dispatch_list(&g);214 owl_io_dispatch *other;215 216 d->fd = fd;217 d->valid = true;218 d->needs_gc = 0;219 d->mode = mode;220 d->callback = cb;221 d->destroy = destroy;222 d->data = data;223 224 /* TODO: Allow changing fd and mode in the middle? Probably don't care... */225 d->pollfd.fd = fd;226 d->pollfd.events = 0;227 if (d->mode & OWL_IO_READ)228 d->pollfd.events |= G_IO_IN | G_IO_HUP | G_IO_ERR;229 if (d->mode & OWL_IO_WRITE)230 d->pollfd.events |= G_IO_OUT | G_IO_ERR;231 if (d->mode & OWL_IO_EXCEPT)232 d->pollfd.events |= G_IO_PRI | G_IO_ERR;233 g_source_add_poll(owl_io_dispatch_source, &d->pollfd);234 235 236 other = owl_select_find_valid_io_dispatch_by_fd(fd);237 if (other)238 owl_select_invalidate_io_dispatch(other);239 owl_list_append_element(dl, d);240 241 return d;242 }243 244 static gboolean owl_io_dispatch_prepare(GSource *source, int *timeout) {245 *timeout = -1;246 return FALSE;247 }248 249 static gboolean owl_io_dispatch_check(GSource *source) {250 int i, len;251 const owl_list *dl;252 253 dl = owl_global_get_io_dispatch_list(&g);254 len = owl_list_get_size(dl);255 for(i = 0; i < len; i++) {256 owl_io_dispatch *d = owl_list_get_element(dl, i);257 if (!d->valid) continue;258 if (d->pollfd.revents & G_IO_NVAL) {259 owl_function_debugmsg("Pruning defunct dispatch on fd %d.", d->fd);260 owl_select_invalidate_io_dispatch(d);261 }262 if (d->pollfd.revents & d->pollfd.events)263 return TRUE;264 }265 return FALSE;266 }267 268 static gboolean owl_io_dispatch_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {269 int i, len;270 const owl_list *dl;271 272 dispatch_active = 1;273 dl = owl_global_get_io_dispatch_list(&g);274 len = owl_list_get_size(dl);275 for (i = 0; i < len; i++) {276 owl_io_dispatch *d = owl_list_get_element(dl, i);277 if (!d->valid) continue;278 if ((d->pollfd.revents & d->pollfd.events) && d->callback != NULL) {279 d->callback(d, d->data);280 }281 }282 dispatch_active = 0;283 owl_select_io_dispatch_gc();284 285 return TRUE;286 }287 288 static GSourceFuncs owl_io_dispatch_funcs = {289 owl_io_dispatch_prepare,290 owl_io_dispatch_check,291 owl_io_dispatch_dispatch,292 NULL293 };294 295 int owl_select_add_perl_io_dispatch(int fd, int mode, SV *cb)296 {297 const owl_io_dispatch *d = owl_select_find_valid_io_dispatch_by_fd(fd);298 if (d != NULL && d->callback != owl_perlconfig_io_dispatch) {299 /* Don't mess with non-perl dispatch functions from here. */300 return 1;301 }302 /* Also remove any invalidated perl dispatch functions that may have303 * stuck around. */304 owl_select_remove_perl_io_dispatch(fd);305 owl_select_add_io_dispatch(fd, mode, owl_perlconfig_io_dispatch, owl_perlconfig_io_dispatch_destroy, cb);306 return 0;307 }308 309 static owl_io_dispatch *owl_select_find_perl_io_dispatch(int fd)310 {311 int i, len;312 const owl_list *dl;313 owl_io_dispatch *d;314 dl = owl_global_get_io_dispatch_list(&g);315 len = owl_list_get_size(dl);316 for(i = 0; i < len; i++) {317 d = owl_list_get_element(dl, i);318 if (d->fd == fd && d->callback == owl_perlconfig_io_dispatch)319 return d;320 }321 return NULL;322 }323 324 int owl_select_remove_perl_io_dispatch(int fd)325 {326 owl_io_dispatch *d = owl_select_find_perl_io_dispatch(fd);327 if (d != NULL) {328 /* Only remove perl io dispatchers from here. */329 owl_select_remove_io_dispatch(d);330 return 0;331 }332 return 1;333 }334 4 335 5 void owl_select_init(void) 336 6 { 337 owl_timer_source = g_source_new(&owl_timer_funcs, sizeof(GSource));338 g_source_attach(owl_timer_source, NULL);339 340 owl_io_dispatch_source = g_source_new(&owl_io_dispatch_funcs, sizeof(GSource));341 g_source_attach(owl_io_dispatch_source, NULL);342 7 } 343 8 344 9 void owl_select_run_loop(void) 345 10 { 346 main_context = g_main_context_default(); 347 loop = g_main_loop_new(main_context, FALSE); 11 loop = g_main_loop_new(NULL, FALSE); 348 12 g_main_loop_run(loop); 349 13 } … … 353 17 if (loop) { 354 18 g_main_loop_quit(loop); 19 g_main_loop_unref(loop); 355 20 loop = NULL; 356 21 }
Note: See TracChangeset
for help on using the changeset viewer.