Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • select.c

    r2f69081 r1895c29  
    22
    33static const char fileIdent[] = "$Id: select.c 894 2008-01-17 07:13:44Z asedeno $";
     4
     5static int dispatch_active = 0;
     6
     7int _owl_select_timer_cmp(owl_timer *t1, owl_timer *t2) {
     8  return t1->time - t2->time;
     9}
     10
     11int _owl_select_timer_eq(owl_timer *t1, owl_timer *t2) {
     12  return t1 == t2;
     13}
     14
     15owl_timer *owl_select_add_timer(int after, int interval, void (*cb)(owl_timer *, void *), void (*destroy)(owl_timer*), void *data)
     16{
     17  owl_timer *t = owl_malloc(sizeof(owl_timer));
     18  GList **timers = owl_global_get_timerlist(&g);
     19
     20  t->time = time(NULL) + after;
     21  t->interval = interval;
     22  t->callback = cb;
     23  t->destroy = destroy;
     24  t->data = data;
     25
     26  *timers = g_list_insert_sorted(*timers, t,
     27                                 (GCompareFunc)_owl_select_timer_cmp);
     28  return t;
     29}
     30
     31void 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    owl_free(t);
     40  }
     41}
     42
     43void owl_select_process_timers(struct timeval *timeout)
     44{
     45  time_t now = time(NULL);
     46  GList **timers = owl_global_get_timerlist(&g);
     47
     48  while(*timers) {
     49    owl_timer *t = (*timers)->data;
     50    int remove = 0;
     51
     52    if(t->time > now)
     53      break;
     54
     55    /* Reschedule if appropriate */
     56    if(t->interval > 0) {
     57      t->time = now + t->interval;
     58      *timers = g_list_remove(*timers, t);
     59      *timers = g_list_insert_sorted(*timers, t,
     60                                     (GCompareFunc)_owl_select_timer_cmp);
     61    } else {
     62      remove = 1;
     63    }
     64
     65    /* Do the callback */
     66    t->callback(t, t->data);
     67    if(remove) {
     68      owl_select_remove_timer(t);
     69    }
     70  }
     71
     72  if(*timers) {
     73    owl_timer *t = (*timers)->data;
     74    timeout->tv_sec = t->time - now;
     75    if (timeout->tv_sec > 60)
     76      timeout->tv_sec = 60;
     77  } else {
     78    timeout->tv_sec = 60;
     79  }
     80
     81  timeout->tv_usec = 0;
     82}
    483
    584/* Returns the index of the dispatch for the file descriptor. */
     
    1998}
    2099
     100void owl_select_remove_dispatch_at(int elt) /* noproto */
     101{
     102  owl_list *dl;
     103  owl_dispatch *d;
     104
     105  dl = owl_global_get_dispatchlist(&g);
     106  d = (owl_dispatch*)owl_list_get_element(dl, elt);
     107  owl_list_remove_element(dl, elt);
     108  if (d->destroy) {
     109    d->destroy(d);
     110  }
     111}
     112
    21113/* Adds a new owl_dispatch to the list, replacing existing ones if needed. */
    22114void owl_select_add_dispatch(owl_dispatch *d)
     
    24116  int elt;
    25117  owl_list *dl;
     118
     119  d->needs_gc = 0;
    26120
    27121  elt = owl_select_find_dispatch(d->fd);
     
    34128       replace the old dispatch. */
    35129    if (d_old != d) {
    36       owl_list_replace_element(dl, elt, d);
    37       owl_free(d_old);
    38     }
    39   }
    40   else {
    41     owl_list_append_element(dl, d);
    42   }
     130      owl_select_remove_dispatch_at(elt);
     131    }
     132  }
     133  owl_list_append_element(dl, d);
    43134}
    44135
     
    48139  int elt;
    49140  owl_list *dl;
     141  owl_dispatch *d;
    50142
    51143  elt = owl_select_find_dispatch(fd);
    52   dl = owl_global_get_dispatchlist(&g);
    53  
    54   if (elt != -1) {
    55     owl_dispatch *d;
     144  if(elt == -1) {
     145    return;
     146  } else if(dispatch_active) {
     147    /* Defer the removal until dispatch is done walking the list */
     148    dl = owl_global_get_dispatchlist(&g);
    56149    d = (owl_dispatch*)owl_list_get_element(dl, elt);
    57     owl_list_remove_element(dl, elt);
    58     if (d->pfunc) {
    59       owl_perlconfig_dispatch_free(d);
    60     }
    61     owl_free(d);
     150    d->needs_gc = 1;
     151  } else {
     152    owl_select_remove_dispatch_at(elt);
    62153  }
    63154}
     
    75166  if (elt != -1) {
    76167    d = (owl_dispatch*)owl_list_get_element(owl_global_get_dispatchlist(&g), elt);
    77     if (d->pfunc == NULL) {
     168    if (d->cfunc != owl_perlconfig_dispatch) {
    78169      /* don't mess with non-perl dispatch functions from here. */
    79170      return 1;
     
    83174  d = malloc(sizeof(owl_dispatch));
    84175  d->fd = fd;
    85   d->cfunc = NULL;
    86   d->pfunc = cb;
     176  d->cfunc = owl_perlconfig_dispatch;
     177  d->destroy = owl_perlconfig_dispatch_free;
     178  d->data = cb;
    87179  owl_select_add_dispatch(d);
    88180  return 0;
     
    97189  if (elt != -1) {
    98190    d = (owl_dispatch*)owl_list_get_element(owl_global_get_dispatchlist(&g), elt);
    99     if (d->pfunc != NULL) {
    100       owl_select_remove_dispatch(fd);
     191    if (d->cfunc == owl_perlconfig_dispatch) {
     192      owl_select_remove_dispatch_at(elt);
    101193      return 0;
    102194    }
     
    125217}
    126218
     219void owl_select_gc()
     220{
     221  int i;
     222  owl_list *dl;
     223
     224  dl = owl_global_get_dispatchlist(&g);
     225  /*
     226   * Count down so we aren't set off by removing items from the list
     227   * during the iteration.
     228   */
     229  for(i = owl_list_get_size(dl) - 1; i >= 0; i--) {
     230    owl_dispatch *d = owl_list_get_element(dl, i);
     231    if(d->needs_gc) {
     232      owl_select_remove_dispatch_at(i);
     233    }
     234  }
     235}
     236
    127237void owl_select_dispatch(fd_set *fds, int max_fd)
    128238{
     
    133243  dl = owl_global_get_dispatchlist(&g);
    134244  len = owl_select_dispatch_count();
     245
     246  dispatch_active = 1;
     247
    135248  for(i = 0; i < len; i++) {
    136249    d = (owl_dispatch*)owl_list_get_element(dl, i);
    137250    /* While d shouldn't normally be null, the list may be altered by
    138251     * functions we dispatch to. */
    139     if (d != NULL && FD_ISSET(d->fd, fds)) {
     252    if (d != NULL && !d->needs_gc && FD_ISSET(d->fd, fds)) {
    140253      if (d->cfunc != NULL) {
    141         (d->cfunc)();
     254        d->cfunc(d);
    142255      }
    143       else if (d->pfunc != NULL) {
    144         owl_perlconfig_do_dispatch(d);
    145       }
    146     }
    147   }
     256    }
     257  }
     258
     259  dispatch_active = 0;
     260  owl_select_gc();
    148261}
    149262
     
    182295  struct timeval timeout;
    183296
    184   timeout.tv_sec = 1;
    185   timeout.tv_usec = 0;
     297  owl_select_process_timers(&timeout);
    186298
    187299  max_fd = owl_select_dispatch_prepare_fd_sets(&r, &e);
Note: See TracChangeset for help on using the changeset viewer.