Changeset df0138f for select.c


Ignore:
Timestamp:
Oct 27, 2009, 12:41:09 AM (14 years ago)
Author:
Alejandro R. Sedeño <asedeno@mit.edu>
Branches:
master, release-1.10, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
ffc4df6
Parents:
f9d257b
git-author:
Alejandro R. Sedeño <asedeno@mit.edu> (10/20/09 20:20:12)
git-committer:
Alejandro R. Sedeño <asedeno@mit.edu> (10/27/09 00:41:09)
Message:
Add a new I/O Dispatch API

Signed-off-by: Alejandro R. Sedeño <asedeno@mit.edu>
File:
1 edited

Legend:

Unmodified
Added
Removed
  • select.c

    r4f2166b rdf0138f  
    203203
    204204  dl = owl_global_get_dispatchlist(&g);
    205   FD_ZERO(r);
    206   FD_ZERO(e);
    207205  max_fd = 0;
    208206  len = owl_select_dispatch_count();
     
    260258}
    261259
     260static const owl_io_dispatch *owl_select_find_io_dispatch_by_fd(const int fd)
     261{
     262  int i, len;
     263  const owl_list *dl;
     264  owl_io_dispatch *d;
     265  dl = owl_global_get_io_dispatch_list(&g);
     266  len = owl_list_get_size(dl);
     267  for(i = 0; i < len; i++) {
     268    d = owl_list_get_element(dl, i);
     269    if (d->fd == fd) return d;
     270  }
     271  return NULL;
     272}
     273
     274static int owl_select_find_io_dispatch(const owl_io_dispatch *in)
     275{
     276  int i, len;
     277  const owl_list *dl;
     278
     279  if (in != NULL) {
     280    dl = owl_global_get_io_dispatch_list(&g);
     281    len = owl_list_get_size(dl);
     282    for(i = 0; i < len; i++) {
     283      const owl_io_dispatch *d = owl_list_get_element(dl, i);
     284      if (d == in) return i;
     285    }
     286  }
     287  return -1;
     288}
     289
     290void owl_select_remove_io_dispatch(const owl_io_dispatch *in)
     291{
     292  int elt;
     293  if (in != NULL) {
     294    elt = owl_select_find_io_dispatch(in);
     295    if (elt != -1) {
     296      owl_list *dl = owl_global_get_io_dispatch_list(&g);
     297      owl_io_dispatch *d = owl_list_get_element(dl, elt);
     298      if (dispatch_active)
     299        d->needs_gc = 1;
     300      else {
     301        owl_list_remove_element(dl, elt);
     302        if (d->destroy)
     303          d->destroy(d);
     304        owl_free(d);
     305      }
     306    }
     307  }
     308}
     309
     310void owl_select_io_dispatch_gc(void)
     311{
     312  int i;
     313  owl_list *dl;
     314
     315  dl = owl_global_get_io_dispatch_list(&g);
     316  /*
     317   * Count down so we aren't set off by removing items from the list
     318   * during the iteration.
     319   */
     320  for(i = owl_list_get_size(dl) - 1; i >= 0; i--) {
     321    owl_io_dispatch *d = owl_list_get_element(dl, i);
     322    if(d->needs_gc) {
     323      owl_select_remove_io_dispatch(d);
     324    }
     325  }
     326}
     327
     328/* Each FD may have at most one dispatcher.
     329 * If a new dispatch is added for an FD, the old one is removed.
     330 * mode determines what types of events are watched for, and may be any combination of:
     331 * OWL_IO_READ, OWL_IO_WRITE, OWL_IO_EXCEPT
     332 */
     333const 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)
     334{
     335  owl_io_dispatch *d = owl_malloc(sizeof(owl_io_dispatch));
     336  owl_list *dl = owl_global_get_io_dispatch_list(&g);
     337
     338  d->fd = fd;
     339  d->needs_gc = 0;
     340  d->mode = mode;
     341  d->callback = cb;
     342  d->destroy = destroy;
     343  d->data = data;
     344
     345  owl_select_remove_io_dispatch(owl_select_find_io_dispatch_by_fd(fd));
     346  owl_list_append_element(dl, d);
     347
     348  return d;
     349}
     350
     351int owl_select_prepare_io_dispatch_fd_sets(fd_set *rfds, fd_set *wfds, fd_set *efds) {
     352  int i, len, max_fd;
     353  owl_io_dispatch *d;
     354  owl_list *dl = owl_global_get_io_dispatch_list(&g);
     355
     356  max_fd = 0;
     357  len = owl_list_get_size(dl);
     358  for (i = 0; i < len; i++) {
     359    d = owl_list_get_element(dl, i);
     360    if (d->mode & (OWL_IO_READ | OWL_IO_WRITE | OWL_IO_EXCEPT)) {
     361      if (max_fd < d->fd) max_fd = d->fd;
     362      if (d->mode & OWL_IO_READ) FD_SET(d->fd, rfds);
     363      if (d->mode & OWL_IO_WRITE) FD_SET(d->fd, wfds);
     364      if (d->mode & OWL_IO_EXCEPT) FD_SET(d->fd, efds);
     365    }
     366  }
     367  return max_fd + 1;
     368}
     369
     370void owl_select_io_dispatch(const fd_set *rfds, const fd_set *wfds, const fd_set *efds, const int max_fd)
     371{
     372  int i, len;
     373  owl_io_dispatch *d;
     374  owl_list *dl = owl_global_get_io_dispatch_list(&g);
     375
     376  dispatch_active = 1;
     377  len = owl_list_get_size(dl);
     378  for (i = 0; i < len; i++) {
     379    d = owl_list_get_element(dl, i);
     380    if (d->fd < max_fd && d->callback != NULL &&
     381        ((d->mode & OWL_IO_READ && FD_ISSET(d->fd, rfds)) ||
     382         (d->mode & OWL_IO_WRITE && FD_ISSET(d->fd, wfds)) ||
     383         (d->mode & OWL_IO_EXCEPT && FD_ISSET(d->fd, efds)))) {
     384      d->callback(d, d->data);
     385    }
     386  }
     387  dispatch_active = 0;
     388  owl_select_io_dispatch_gc();
     389}
     390
     391int owl_select_add_perl_io_dispatch(int fd, int mode, SV *cb)
     392{
     393  const owl_io_dispatch *d = owl_select_find_io_dispatch_by_fd(fd);
     394  if (d != NULL && d->callback != owl_perlconfig_io_dispatch) {
     395    /* Don't mess with non-perl dispatch functions from here. */
     396    return 1;
     397  }
     398  owl_select_add_io_dispatch(fd, mode, owl_perlconfig_io_dispatch, owl_perlconfig_io_dispatch_destroy, cb);
     399  return 0;
     400}
     401
     402int owl_select_remove_perl_io_dispatch(int fd)
     403{
     404  const owl_io_dispatch *d = owl_select_find_io_dispatch_by_fd(fd);
     405  if (d != NULL && d->callback == owl_perlconfig_io_dispatch) {
     406    /* Only remove perl io dispatchers from here. */
     407    owl_select_remove_io_dispatch(d);
     408    return 0;
     409  }
     410  return 1;
     411}
     412
    262413int owl_select_aim_hack(fd_set *rfds, fd_set *wfds)
    263414{
     
    266417  int max_fd;
    267418
    268   FD_ZERO(rfds);
    269   FD_ZERO(wfds);
    270419  max_fd = 0;
    271420  sess = owl_global_get_aimsess(&g);
     
    414563void owl_select(void)
    415564{
    416   int i, max_fd, aim_max_fd, aim_done, ret;
     565  int i, max_fd, max_fd2, aim_done, ret;
    417566  fd_set r;
     567  fd_set w;
    418568  fd_set e;
    419569  fd_set aim_rfds, aim_wfds;
     
    430580    return;
    431581  }
     582  FD_ZERO(&r);
     583  FD_ZERO(&w);
     584  FD_ZERO(&e);
    432585
    433586  max_fd = owl_select_dispatch_prepare_fd_sets(&r, &e);
     587  max_fd2 = owl_select_prepare_io_dispatch_fd_sets(&r, &w, &e);
     588  if (max_fd < max_fd2) max_fd = max_fd2;
    434589
    435590  /* AIM HACK:
     
    448603  if (owl_global_is_doaimevents(&g)) {
    449604    aim_done = 0;
    450     aim_max_fd = owl_select_aim_hack(&aim_rfds, &aim_wfds);
    451     if (max_fd < aim_max_fd) max_fd = aim_max_fd;
    452     for(i = 0; i <= aim_max_fd; i++) {
     605    max_fd2 = owl_select_aim_hack(&aim_rfds, &aim_wfds);
     606    if (max_fd < max_fd2) max_fd = max_fd2;
     607    for(i = 0; i <= max_fd2; i++) {
    453608      if (FD_ISSET(i, &aim_rfds)) {
    454609        FD_SET(i, &r);
    455610        FD_SET(i, &e);
    456611      }
     612      if (FD_ISSET(i, &aim_wfds)) {
     613        FD_SET(i, &w);
     614        FD_SET(i, &e);
     615      }
    457616    }
    458617  }
     
    464623  }
    465624
    466   ret = pselect(max_fd+1, &r, &aim_wfds, &e, &timeout, &mask);
     625  ret = pselect(max_fd+1, &r, &w, &e, &timeout, &mask);
    467626
    468627  if(ret < 0 && errno == EINTR) {
     
    482641      /* Merge all interesting FDs into one set, since we have a
    483642         single dispatch per FD. */
    484       if (FD_ISSET(i, &r) || FD_ISSET(i, &aim_wfds) || FD_ISSET(i, &e)) {
     643      if (FD_ISSET(i, &r) || FD_ISSET(i, &w) || FD_ISSET(i, &e)) {
    485644        /* AIM HACK: no separate dispatch, just process here if
    486645           needed, and only once per run through. */
     
    497656       and read ready FDs. */
    498657    owl_select_dispatch(&r, max_fd);
    499   }
    500 }
     658    owl_select_io_dispatch(&r, &w, &e, max_fd);
     659  }
     660}
Note: See TracChangeset for help on using the changeset viewer.