Changeset 2c79eae


Ignore:
Timestamp:
May 23, 2011, 8:57:46 PM (13 years ago)
Author:
David Benjamin <davidben@mit.edu>
Branches:
master, release-1.10, release-1.8, release-1.9
Children:
4cc49bc
Parents:
1255365
git-author:
David Benjamin <davidben@mit.edu> (12/29/10 07:20:12)
git-committer:
David Benjamin <davidben@mit.edu> (05/23/11 20:57: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. Keep owl_select around for now as
reference.
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • global.c

    r47e0a6a r2c79eae  
    1616
    1717  g_type_init();
     18
     19  owl_select_init();
    1820
    1921  g->lines=LINES;
  • owl.h

    rfeeb835 r2c79eae  
    550550  void (*destroy)(const struct _owl_io_dispatch *);  /* Destructor */
    551551  void *data;
     552  GPollFD pollfd;
    552553} owl_io_dispatch;
    553554
  • select.c

    rebb8498 r2c79eae  
    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;
    69
    710static int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2) {
     
    3942}
    4043
    41 void owl_select_process_timers(struct timespec *timeout)
    42 {
    43   time_t now = time(NULL);
     44static gboolean owl_timer_prepare(GSource *source, int *timeout) {
    4445  GList **timers = owl_global_get_timerlist(&g);
    45 
     46  GTimeVal now;
     47
     48  /* TODO: In the far /far/ future, g_source_get_time is what the cool
     49   * 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
     68static 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 cool
     73   * 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
     85static 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 cool
     90   * 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? */
    4694  while(*timers) {
    4795    owl_timer *t = (*timers)->data;
    4896    int remove = 0;
    4997
    50     if(t->time > now)
     98    if(t->time > now.tv_sec)
    5199      break;
    52100
    53101    /* Reschedule if appropriate */
    54102    if(t->interval > 0) {
    55       t->time = now + t->interval;
     103      t->time = now.tv_sec + t->interval;
    56104      *timers = g_list_remove(*timers, t);
    57105      *timers = g_list_insert_sorted(*timers, t,
     
    67115    }
    68116  }
    69 
    70   if(*timers) {
    71     owl_timer *t = (*timers)->data;
    72     timeout->tv_sec = t->time - now;
    73     if (timeout->tv_sec > 60)
    74       timeout->tv_sec = 60;
    75   } else {
    76     timeout->tv_sec = 60;
    77   }
    78 
    79   timeout->tv_nsec = 0;
    80 }
     117  return TRUE;
     118}
     119
     120static GSourceFuncs owl_timer_funcs = {
     121  owl_timer_prepare,
     122  owl_timer_check,
     123  owl_timer_dispatch,
     124  NULL
     125};
     126
    81127
    82128static const owl_io_dispatch *owl_select_find_io_dispatch_by_fd(const int fd)
     
    124170        if (d->destroy)
    125171          d->destroy(d);
     172        g_source_remove_poll(owl_io_dispatch_source, &d->pollfd);
    126173        g_free(d);
    127174      }
     
    165212  d->data = data;
    166213
     214  /* TODO: Allow changing fd and mode in the middle? Probably don't care... */
     215  d->pollfd.fd = fd;
     216  d->pollfd.events = 0;
     217  if (d->mode & OWL_IO_READ)
     218    d->pollfd.events |= G_IO_IN | G_IO_HUP | G_IO_ERR;
     219  if (d->mode & OWL_IO_WRITE)
     220    d->pollfd.events |= G_IO_OUT | G_IO_ERR;
     221  if (d->mode & OWL_IO_EXCEPT)
     222    d->pollfd.events |= G_IO_PRI | G_IO_ERR;
     223  g_source_add_poll(owl_io_dispatch_source, &d->pollfd);
     224
     225
    167226  owl_select_remove_io_dispatch(owl_select_find_io_dispatch_by_fd(fd));
    168227  owl_list_append_element(dl, d);
     
    171230}
    172231
    173 int owl_select_prepare_io_dispatch_fd_sets(fd_set *rfds, fd_set *wfds, fd_set *efds) {
    174   int i, len, max_fd;
    175   owl_io_dispatch *d;
    176   owl_list *dl = owl_global_get_io_dispatch_list(&g);
    177 
    178   max_fd = 0;
     232static gboolean owl_io_dispatch_prepare(GSource *source, int *timeout) {
     233  owl_select_do_pre_select_actions(); /* HACK */
     234  *timeout = -1;
     235  return FALSE;
     236}
     237
     238static gboolean owl_io_dispatch_check(GSource *source) {
     239  int i, len;
     240  const owl_list *dl;
     241
     242  dl = owl_global_get_io_dispatch_list(&g);
     243  len = owl_list_get_size(dl);
     244  for(i = 0; i < len; i++) {
     245    const owl_io_dispatch *d = owl_list_get_element(dl, i);
     246    if (d->pollfd.revents & d->pollfd.events)
     247      return TRUE;
     248  }
     249  return FALSE;
     250}
     251
     252static gboolean owl_io_dispatch_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
     253  int i, len;
     254  const owl_list *dl;
     255
     256  dispatch_active = 1;
     257  dl = owl_global_get_io_dispatch_list(&g);
    179258  len = owl_list_get_size(dl);
    180259  for (i = 0; i < len; i++) {
    181     d = owl_list_get_element(dl, i);
    182     if (d->mode & (OWL_IO_READ | OWL_IO_WRITE | OWL_IO_EXCEPT)) {
    183       if (max_fd < d->fd) max_fd = d->fd;
    184       if (d->mode & OWL_IO_READ) FD_SET(d->fd, rfds);
    185       if (d->mode & OWL_IO_WRITE) FD_SET(d->fd, wfds);
    186       if (d->mode & OWL_IO_EXCEPT) FD_SET(d->fd, efds);
    187     }
    188   }
    189   return max_fd + 1;
    190 }
    191 
    192 void owl_select_io_dispatch(const fd_set *rfds, const fd_set *wfds, const fd_set *efds, const int max_fd)
    193 {
    194   int i, len;
    195   owl_io_dispatch *d;
    196   owl_list *dl = owl_global_get_io_dispatch_list(&g);
    197 
    198   dispatch_active = 1;
    199   len = owl_list_get_size(dl);
    200   for (i = 0; i < len; i++) {
    201     d = owl_list_get_element(dl, i);
    202     if (d->fd < max_fd && d->callback != NULL &&
    203         ((d->mode & OWL_IO_READ && FD_ISSET(d->fd, rfds)) ||
    204          (d->mode & OWL_IO_WRITE && FD_ISSET(d->fd, wfds)) ||
    205          (d->mode & OWL_IO_EXCEPT && FD_ISSET(d->fd, efds)))) {
     260    owl_io_dispatch *d = owl_list_get_element(dl, i);
     261    if ((d->pollfd.revents & d->pollfd.events) && d->callback != NULL) {
    206262      d->callback(d, d->data);
    207263    }
     
    209265  dispatch_active = 0;
    210266  owl_select_io_dispatch_gc();
    211 }
     267
     268  return TRUE;
     269}
     270
     271static GSourceFuncs owl_io_dispatch_funcs = {
     272  owl_io_dispatch_prepare,
     273  owl_io_dispatch_check,
     274  owl_io_dispatch_dispatch,
     275  NULL
     276};
    212277
    213278int owl_select_add_perl_io_dispatch(int fd, int mode, SV *cb)
     
    351416}
    352417
     418#if 0
     419/* FIXME: Reimplement the AIM hack and handle AIM events. */
    353420void owl_select(void)
    354421{
     
    435502  }
    436503}
     504#endif
     505
     506void owl_select_init(void)
     507{
     508  owl_timer_source = g_source_new(&owl_timer_funcs, sizeof(GSource));
     509  g_source_attach(owl_timer_source, NULL);
     510
     511  owl_io_dispatch_source = g_source_new(&owl_io_dispatch_funcs, sizeof(GSource));
     512  g_source_attach(owl_io_dispatch_source, NULL);
     513}
    437514
    438515void owl_select_run_loop(void)
    439516{
    440   loop_active = 1;
    441   while (loop_active) {
    442     owl_select();
    443   }
     517  loop = g_main_loop_new(NULL, FALSE);
     518  g_main_loop_run(loop);
    444519}
    445520
    446521void owl_select_quit_loop(void)
    447522{
    448   loop_active = 0;
    449 }
     523  if (loop) {
     524    g_main_loop_quit(loop);
     525    loop = NULL;
     526  }
     527}
Note: See TracChangeset for help on using the changeset viewer.