Show
Ignore:
Timestamp:
12/04/08 22:19:49 (9 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1228429189 +0000
git-parent:

[df2e1eb8a0d6b779a1327d8df4d867b961ce4b07]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1228429189 +0000
Message:

Add trigger support, compiles on Mac OS X and Solaris, changes made to Linux, but untested (even compile), refs #65

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/eventer/eventer_ports_impl.c

    rdf2e1eb r04aaf95  
    201201static eventer_t eventer_ports_impl_find_fd(int fd) { 
    202202  return master_fds[fd].e; 
     203} 
     204static void 
     205eventer_ports_impl_trigger(eventer_t e, int mask) { 
     206  ev_lock_state_t lockstate; 
     207  const char *cbname; 
     208  struct timeval __now; 
     209  int fd, oldmask, newmask; 
     210 
     211  fd = e->fd; 
     212  if(e != master_fds[fd].e) return; 
     213  lockstate = acquire_master_fd(fd); 
     214  if(lockstate == EV_ALREADY_OWNED) return; 
     215  assert(lockstate == EV_OWNED); 
     216 
     217  gettimeofday(&__now, NULL); 
     218  oldmask = e->mask; 
     219  cbname = eventer_name_for_callback(e->callback); 
     220  noitLT(eventer_deb, &__now, "ports: fire on %d/%x to %s(%p)\n", 
     221         fd, mask, cbname?cbname:"???", e->callback); 
     222  newmask = e->callback(e, mask, e->closure, &__now); 
     223 
     224  if(newmask) { 
     225    alter_fd(e, newmask); 
     226    /* Set our mask */ 
     227    e->mask = newmask; 
     228  } 
     229  else { 
     230    /* 
     231     * Long story long: 
     232     *  When integrating with a few external event systems, we find 
     233     *  it difficult to make their use of remove+add as an update 
     234     *  as it can be recurrent in a single handler call and you cannot 
     235     *  remove completely from the event system if you are going to 
     236     *  just update (otherwise the eventer_t in your call stack could 
     237     *  be stale).  What we do is perform a superficial remove, marking 
     238     *  the mask as 0, but not eventer_remove_fd.  Then on an add, if 
     239     *  we already have an event, we just update the mask (as we 
     240     *  have not yet returned to the eventer's loop. 
     241     *  This leaves us in a tricky situation when a remove is called 
     242     *  and the add doesn't roll in, we return 0 (mask == 0) and hit 
     243     *  this spot.  We have intended to remove the event, but it still 
     244     *  resides at master_fds[fd].e -- even after we free it. 
     245     *  So, in the evnet that we return 0 and the event that 
     246     *  master_fds[fd].e == the event we're about to free... we NULL 
     247     *  it out. 
     248     */ 
     249    if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
     250    eventer_free(e); 
     251  } 
     252  release_master_fd(fd, lockstate); 
    203253} 
    204254static int eventer_ports_impl_loop() { 
     
    285335      /* Loop a last time to process */ 
    286336      for(idx = 0; idx < fd_cnt; idx++) { 
    287         ev_lock_state_t lockstate; 
    288337        port_event_t *pe; 
    289338        eventer_t e; 
     
    305354         * before we got here. 
    306355         */ 
    307         if(e != master_fds[fd].e) continue; 
    308         lockstate = acquire_master_fd(fd); 
    309         assert(lockstate == EV_OWNED); 
    310  
    311         gettimeofday(&__now, NULL); 
    312         oldmask = e->mask; 
    313         cbname = eventer_name_for_callback(e->callback); 
    314         noitLT(eventer_deb, &__now, "ports: fire on %d/%x to %s(%p)\n", 
    315                fd, mask, cbname?cbname:"???", e->callback); 
    316         newmask = e->callback(e, mask, e->closure, &__now); 
    317  
    318         if(newmask) { 
    319           alter_fd(e, newmask); 
    320           /* Set our mask */ 
    321           e->mask = newmask; 
    322         } 
    323         else { 
    324           /* 
    325            * Long story long: 
    326            *  When integrating with a few external event systems, we find 
    327            *  it difficult to make their use of remove+add as an update 
    328            *  as it can be recurrent in a single handler call and you cannot 
    329            *  remove completely from the event system if you are going to 
    330            *  just update (otherwise the eventer_t in your call stack could 
    331            *  be stale).  What we do is perform a superficial remove, marking 
    332            *  the mask as 0, but not eventer_remove_fd.  Then on an add, if 
    333            *  we already have an event, we just update the mask (as we 
    334            *  have not yet returned to the eventer's loop. 
    335            *  This leaves us in a tricky situation when a remove is called 
    336            *  and the add doesn't roll in, we return 0 (mask == 0) and hit 
    337            *  this spot.  We have intended to remove the event, but it still 
    338            *  resides at master_fds[fd].e -- even after we free it. 
    339            *  So, in the evnet that we return 0 and the event that 
    340            *  master_fds[fd].e == the event we're about to free... we NULL 
    341            *  it out. 
    342            */ 
    343           if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
    344           eventer_free(e); 
    345         } 
    346         release_master_fd(fd, lockstate); 
     356        eventer_ports_impl_trigger(e, mask); 
    347357      } 
    348358    } 
     
    360370  eventer_ports_impl_remove_fd, 
    361371  eventer_ports_impl_find_fd, 
     372  eventer_ports_impl_trigger, 
    362373  eventer_ports_impl_loop 
    363374};