Changeset b279013 for select.c


Ignore:
Timestamp:
Mar 25, 2011, 3:46:46 AM (11 years ago)
Author:
David Benjamin <davidben@mit.edu>
Children:
7b2686d
Parents:
e9b037f
git-author:
David Benjamin <davidben@mit.edu> (12/29/10 07:20:12)
git-committer:
David Benjamin <davidben@mit.edu> (03/25/11 03:46:46)
Message:
Start of GMainContext code

Add GSources to feed owl_timer and owl_io_dispatch events into the main
loop. Also add a hack so pre-select actions run at all. Glib's main loop
has a hard priority system, so it prefers that prepare/check hooks
return if the event would actually do anything. We probably want to
replace every pre-select action with a dedicated GSource (or maybe a
bunch of g_idle_add calls).

Signals are also racy right now; glib uses select/poll instead of
pselect/ppoll, so you can't actually listen for signals on the same
thread. (In fact, the single-threaded version of g_child_watch_add
doesn't actually work.) That's okay as what we were doing doesn't work
when you add a second thread and thread safety is sort of the point of
this work.

The AIM hack need also be restored.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • select.c

    rd4927a7 rb279013  
    11#include "owl.h"
    22
     3static GMainLoop *loop = NULL;
    34static int dispatch_active = 0;
    45static int psa_active = 0;
    5 static int loop_active = 0;
     6
     7static GSource *owl_timer_source;
     8static GSource *owl_io_dispatch_source;
     9
     10static gboolean owl_timer_prepare(GSource *source, int *timeout) {
     11  GList **timers = owl_global_get_timerlist(&g);
     12  GTimeVal now;
     13
     14  /* TODO: In the far /far/ future, g_source_get_time is what the cool
     15   * kids use to get system monotonic time. */
     16  g_source_get_current_time(source, &now);
     17
     18  /* FIXME: bother with millisecond accuracy now that we can? */
     19  if (*timers) {
     20    owl_timer *t = (*timers)->data;
     21    *timeout = t->time - now.tv_sec;
     22    if (*timeout <= 0) {
     23      *timeout = 0;
     24      return TRUE;
     25    }
     26    if (*timeout > 60 * 1000)
     27      *timeout = 60 * 1000;
     28  } else {
     29    *timeout = 60 * 1000;
     30  }
     31  return FALSE;
     32}
     33
     34static gboolean owl_timer_check(GSource *source) {
     35  GList **timers = owl_global_get_timerlist(&g);
     36  GTimeVal now;
     37
     38  /* TODO: In the far /far/ future, g_source_get_time is what the cool
     39   * kids use to get system monotonic time. */
     40  g_source_get_current_time(source, &now);
     41
     42  /* FIXME: bother with millisecond accuracy now that we can? */
     43  if (*timers) {
     44    owl_timer *t = (*timers)->data;
     45    return t->time >= now.tv_sec;
     46  }
     47  return FALSE;
     48}
     49
     50
     51static gboolean owl_timer_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
     52  GList **timers = owl_global_get_timerlist(&g);
     53  GTimeVal now;
     54
     55  /* TODO: In the far /far/ future, g_source_get_time is what the cool
     56   * kids use to get system monotonic time. */
     57  g_source_get_current_time(source, &now);
     58
     59  /* FIXME: bother with millisecond accuracy now that we can? */
     60  while(*timers) {
     61    owl_timer *t = (*timers)->data;
     62    int remove = 0;
     63
     64    if(t->time > now.tv_sec)
     65      break;
     66
     67    /* Reschedule if appropriate */
     68    if(t->interval > 0) {
     69      t->time = now.tv_sec + t->interval;
     70      *timers = g_list_remove(*timers, t);
     71      *timers = g_list_insert_sorted(*timers, t,
     72                                     (GCompareFunc)_owl_select_timer_cmp);
     73    } else {
     74      remove = 1;
     75    }
     76
     77    /* Do the callback */
     78    t->callback(t, t->data);
     79    if(remove) {
     80      owl_select_remove_timer(t);
     81    }
     82  }
     83  return TRUE;
     84}
     85
     86static GSourceFuncs owl_timer_funcs = {
     87  owl_timer_prepare,
     88  owl_timer_check,
     89  owl_timer_dispatch,
     90  NULL
     91};
    692
    793int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2) {
     
    43129}
    44130
    45 void owl_select_process_timers(struct timespec *timeout)
    46 {
    47   time_t now = time(NULL);
    48   GList **timers = owl_global_get_timerlist(&g);
    49 
    50   while(*timers) {
    51     owl_timer *t = (*timers)->data;
    52     int remove = 0;
    53 
    54     if(t->time > now)
    55       break;
    56 
    57     /* Reschedule if appropriate */
    58     if(t->interval > 0) {
    59       t->time = now + t->interval;
    60       *timers = g_list_remove(*timers, t);
    61       *timers = g_list_insert_sorted(*timers, t,
    62                                      (GCompareFunc)_owl_select_timer_cmp);
    63     } else {
    64       remove = 1;
    65     }
    66 
    67     /* Do the callback */
    68     t->callback(t, t->data);
    69     if(remove) {
    70       owl_select_remove_timer(t);
    71     }
    72   }
    73 
    74   if(*timers) {
    75     owl_timer *t = (*timers)->data;
    76     timeout->tv_sec = t->time - now;
    77     if (timeout->tv_sec > 60)
    78       timeout->tv_sec = 60;
    79   } else {
    80     timeout->tv_sec = 60;
    81   }
    82 
    83   timeout->tv_nsec = 0;
    84 }
     131
     132static gboolean owl_io_dispatch_prepare(GSource *source, int *timeout) {
     133  owl_select_do_pre_select_actions(); /* HACK */
     134  *timeout = -1;
     135  return FALSE;
     136}
     137
     138static gboolean owl_io_dispatch_check(GSource *source) {
     139  int i, len;
     140  const owl_list *dl;
     141
     142  dl = owl_global_get_io_dispatch_list(&g);
     143  len = owl_list_get_size(dl);
     144  for(i = 0; i < len; i++) {
     145    const owl_io_dispatch *d = owl_list_get_element(dl, i);
     146    if (d->pollfd.revents & d->pollfd.events)
     147      return TRUE;
     148  }
     149  return FALSE;
     150}
     151
     152static gboolean owl_io_dispatch_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
     153  int i, len;
     154  const owl_list *dl;
     155 
     156  dispatch_active = 1;
     157  dl = owl_global_get_io_dispatch_list(&g);
     158  len = owl_list_get_size(dl);
     159  for (i = 0; i < len; i++) {
     160    owl_io_dispatch *d = owl_list_get_element(dl, i);
     161    if ((d->pollfd.revents & d->pollfd.events) && d->callback != NULL) {
     162      d->callback(d, d->data);
     163    }
     164  }
     165  dispatch_active = 0;
     166  owl_select_io_dispatch_gc();
     167
     168  return TRUE;
     169}
     170
     171static GSourceFuncs owl_io_dispatch_funcs = {
     172  owl_io_dispatch_prepare,
     173  owl_io_dispatch_check,
     174  owl_io_dispatch_dispatch,
     175  NULL
     176};
    85177
    86178static const owl_io_dispatch *owl_select_find_io_dispatch_by_fd(const int fd)
     
    128220        if (d->destroy)
    129221          d->destroy(d);
     222        g_source_remove_poll(owl_io_dispatch_source, &d->pollfd);
    130223        g_free(d);
    131224      }
     
    169262  d->data = data;
    170263
     264  /* TODO: Allow changing fd and mode in the middle? Probably don't care... */
     265  d->pollfd.fd = fd;
     266  d->pollfd.events = 0;
     267  if (d->mode & OWL_IO_READ)
     268    d->pollfd.events |= G_IO_IN | G_IO_HUP | G_IO_ERR;
     269  if (d->mode & OWL_IO_WRITE)
     270    d->pollfd.events |= G_IO_OUT | G_IO_ERR;
     271  if (d->mode & OWL_IO_EXCEPT)
     272    d->pollfd.events |= G_IO_PRI | G_IO_ERR;
     273  g_source_add_poll(owl_io_dispatch_source, &d->pollfd);
     274
     275
    171276  owl_select_remove_io_dispatch(owl_select_find_io_dispatch_by_fd(fd));
    172277  owl_list_append_element(dl, d);
    173278
    174279  return d;
    175 }
    176 
    177 int owl_select_prepare_io_dispatch_fd_sets(fd_set *rfds, fd_set *wfds, fd_set *efds) {
    178   int i, len, max_fd;
    179   owl_io_dispatch *d;
    180   owl_list *dl = owl_global_get_io_dispatch_list(&g);
    181 
    182   max_fd = 0;
    183   len = owl_list_get_size(dl);
    184   for (i = 0; i < len; i++) {
    185     d = owl_list_get_element(dl, i);
    186     if (d->mode & (OWL_IO_READ | OWL_IO_WRITE | OWL_IO_EXCEPT)) {
    187       if (max_fd < d->fd) max_fd = d->fd;
    188       if (d->mode & OWL_IO_READ) FD_SET(d->fd, rfds);
    189       if (d->mode & OWL_IO_WRITE) FD_SET(d->fd, wfds);
    190       if (d->mode & OWL_IO_EXCEPT) FD_SET(d->fd, efds);
    191     }
    192   }
    193   return max_fd + 1;
    194 }
    195 
    196 void owl_select_io_dispatch(const fd_set *rfds, const fd_set *wfds, const fd_set *efds, const int max_fd)
    197 {
    198   int i, len;
    199   owl_io_dispatch *d;
    200   owl_list *dl = owl_global_get_io_dispatch_list(&g);
    201 
    202   dispatch_active = 1;
    203   len = owl_list_get_size(dl);
    204   for (i = 0; i < len; i++) {
    205     d = owl_list_get_element(dl, i);
    206     if (d->fd < max_fd && d->callback != NULL &&
    207         ((d->mode & OWL_IO_READ && FD_ISSET(d->fd, rfds)) ||
    208          (d->mode & OWL_IO_WRITE && FD_ISSET(d->fd, wfds)) ||
    209          (d->mode & OWL_IO_EXCEPT && FD_ISSET(d->fd, efds)))) {
    210       d->callback(d, d->data);
    211     }
    212   }
    213   dispatch_active = 0;
    214   owl_select_io_dispatch_gc();
    215280}
    216281
     
    355420}
    356421
     422#if 0
    357423void owl_select(void)
    358424{
     
    439505  }
    440506}
     507#endif
     508
     509void owl_select_init(void)
     510{
     511  owl_timer_source = g_source_new(&owl_timer_funcs, sizeof(GSource));
     512  g_source_attach(owl_timer_source, NULL);
     513
     514  owl_io_dispatch_source = g_source_new(&owl_io_dispatch_funcs, sizeof(GSource));
     515  g_source_attach(owl_io_dispatch_source, NULL);
     516}
    441517
    442518void owl_select_run_loop(void)
    443519{
    444   loop_active = 1;
    445   while (loop_active) {
    446     owl_select();
    447   }
     520  loop = g_main_loop_new(NULL, FALSE);
     521  g_main_loop_run(loop);
    448522}
    449523
    450524void owl_select_quit_loop(void)
    451525{
    452   loop_active = 0;
    453 }
     526  if (loop) {
     527    g_main_loop_quit(loop);
     528    loop = NULL;
     529  }
     530}
Note: See TracChangeset for help on using the changeset viewer.