Changeset df0138f05e0bae986f09d167195c6ce676bac37d

Show
Ignore:
Timestamp:
10/27/09 00:41:09 (4 weeks ago)
Author:
Alejandro R. Sedeño <asedeno@mit.edu>
git-author:
Alejandro R. Sedeño <asedeno@mit.edu> / 2009-10-20T20:20:12Z-0400
Parents:
f9d257b7036a557ba1d61d6149c5801dbda10d41
Children:
ffc4df61a846d99a75783f7d348fb98dd19910aa
git-committer:
Alejandro R. Sedeño <asedeno@mit.edu> / 2009-10-27T00:41:09Z-0400
Message:
Add a new I/O Dispatch API

Signed-off-by: Alejandro R. Sedeño <asedeno@mit.edu>
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • global.c

    r23fddad rdf0138f  
    113113  owl_message_init_fmtext_cache(); 
    114114  owl_list_create(&(g->dispatchlist)); 
     115  owl_list_create(&(g->io_dispatch_list)); 
    115116  owl_list_create(&(g->psa_list)); 
    116117  g->timerlist = NULL; 
     
    945946} 
    946947 
     948owl_list *owl_global_get_io_dispatch_list(owl_global *g) 
     949{ 
     950  return &(g->io_dispatch_list); 
     951} 
     952 
    947953owl_list *owl_global_get_psa_list(owl_global *g) 
    948954{ 
  • owl.h

    r6337cb5 rdf0138f  
    105105#define OWL_MESSAGE_DIRECTION_OUT   2 
    106106 
    107 #define OWL_MUX_READ   1 
    108 #define OWL_MUX_WRITE  2 
    109 #define OWL_MUX_EXCEPT 4 
     107#define OWL_IO_READ   1 
     108#define OWL_IO_WRITE  2 
     109#define OWL_IO_EXCEPT 4 
    110110 
    111111#define OWL_DIRECTION_NONE      0 
     
    508508  void *data; 
    509509} owl_dispatch; 
     510 
     511typedef struct _owl_io_dispatch { 
     512  int fd;                                     /* FD to watch for dispatch. */ 
     513  int mode; 
     514  int needs_gc; 
     515  void (*callback)(const struct _owl_io_dispatch *, void *); /* C function to dispatch to. */ 
     516  void (*destroy)(const struct _owl_io_dispatch *);  /* Destructor */ 
     517  void *data; 
     518} owl_io_dispatch; 
    510519 
    511520typedef struct _owl_ps_action { 
     
    595604  owl_obarray obarray; 
    596605  owl_list dispatchlist; 
     606  owl_list io_dispatch_list; 
    597607  owl_list psa_list; 
    598608  GList *timerlist; 
  • perlconfig.c

    rfb7742c rdf0138f  
    510510} 
    511511 
     512void owl_perlconfig_io_dispatch_destroy(const owl_io_dispatch *d) 
     513{ 
     514  SvREFCNT_dec(d->data); 
     515} 
     516 
    512517void owl_perlconfig_edit_callback(owl_editwin *e) 
    513518{ 
     
    580585} 
    581586 
     587void owl_perlconfig_io_dispatch(const owl_io_dispatch *d, void *data) 
     588{ 
     589  SV *cb = data; 
     590  dSP; 
     591  if(cb == NULL) { 
     592    owl_function_error("Perl callback is NULL!"); 
     593    return; 
     594  } 
     595 
     596  ENTER; 
     597  SAVETMPS; 
     598 
     599  PUSHMARK(SP); 
     600  PUTBACK; 
     601 
     602  call_sv(cb, G_DISCARD|G_KEEPERR|G_EVAL); 
     603 
     604  if(SvTRUE(ERRSV)) { 
     605    owl_function_error("%s", SvPV_nolen(ERRSV)); 
     606  } 
     607 
     608  FREETMPS; 
     609  LEAVE; 
     610} 
     611 
    582612void owl_perlconfig_perl_timer(owl_timer *t, void *data) 
    583613{ 
  • 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}