Only do one event at a time to a callback.

This commit is contained in:
Nils O. Selåsdal
2013-11-09 11:06:19 +01:00
parent a4c6b65d5f
commit 6b26812cf3
3 changed files with 38 additions and 27 deletions
+3 -2
View File
@@ -42,10 +42,11 @@ struct IOMux;
struct IOMuxFD; struct IOMuxFD;
/** Callback function used in struct IOMuxFD /** Callback function used in struct IOMuxFD
*
* @param mux the mux that issued the callback. * @param mux the mux that issued the callback.
* @param fd the file desciptor structure. * @param fd the file desciptor structure.
* @param event A bitmask of the MUX_EV_XX values. Both a read and a write event * @param event A bitmask of the MUX_EV_XX values. Only one event(bit)
* might be signalled in the same callback * will be signalled in the same callback
*/ */
typedef void (*iomux_cb)(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event); typedef void (*iomux_cb)(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event);
+19 -10
View File
@@ -162,7 +162,7 @@ static int iomux_epoll_run(struct IOMux *mux_, struct timeval *timeout)
rc = epoll_wait(mux->epoll_fd, mux->pending_events, EPOLL_WAIT_EVENTS, timeout_ms); rc = epoll_wait(mux->epoll_fd, mux->pending_events, EPOLL_WAIT_EVENTS, timeout_ms);
while (rc == -1 && errno == EINTR) } while (rc == -1 && errno == EINTR);
assert(rc >= 0); assert(rc >= 0);
if(rc < 0) if(rc < 0)
@@ -177,18 +177,27 @@ static int iomux_epoll_run(struct IOMux *mux_, struct timeval *timeout)
for (i = 0; i < rc; i++) { for (i = 0; i < rc; i++) {
struct IOMuxFD *fd = mux->pending_events[i].data.ptr; struct IOMuxFD *fd = mux->pending_events[i].data.ptr;
if (fd != NULL) { //calling _unregister from a callback could have removed it unsigned int events;
unsigned int events;
events = epoll_2_mux_events(mux->pending_events[i].events); events = epoll_2_mux_events(mux->pending_events[i].events);
//we want to deliver only one event at a time to simplify
//application programming.
fd = mux->pending_events[i].data.ptr;
if (events & MUX_EV_READ && fd != NULL) {
assert(fd->callback != NULL); assert(fd->callback != NULL);
fd->callback(mux_, fd, events); fd->callback(mux_, fd, MUX_EV_READ);
//be sure not to use fd after the callback, it might been removed.
mux->pending_events[i].data.ptr = NULL; //clear from pending list
event_cnt++;
} }
//now re-check, in case the IOMuxFD was removed
fd = mux->pending_events[i].data.ptr;
if (events & MUX_EV_WRITE && fd != NULL) {
assert(fd->callback != NULL);
fd->callback(mux_, fd, MUX_EV_WRITE);
}
event_cnt += events != 0;
} }
mux->pending = 0; mux->pending = 0;
+16 -15
View File
@@ -150,7 +150,7 @@ static int iomux_select_run(struct IOMux *mux_, struct timeval *timeout)
write_set = mux->master_write_set; write_set = mux->master_write_set;
rc = select(mux->max_fd + 1, &read_set, &write_set, NULL, timeout); //we can use timeout directly rc = select(mux->max_fd + 1, &read_set, &write_set, NULL, timeout); //we can use timeout directly
while (rc == -1 && errno == EINTR) } while (rc == -1 && errno == EINTR);
assert(rc >= 0); assert(rc >= 0);
if (rc < 0) if (rc < 0)
@@ -164,25 +164,26 @@ static int iomux_select_run(struct IOMux *mux_, struct timeval *timeout)
for (i = 0; rc > 0 && i < mux->num_descriptors; i++) { for (i = 0; rc > 0 && i < mux->num_descriptors; i++) {
unsigned int events = 0; unsigned int events = 0;
if (mux->descriptors[i] == NULL) { //callback might have deleted it //deliver only one event at a time , to simplify application
continue; //programming
if (mux->descriptors[i] != NULL &&
FD_ISSET(mux->descriptors[i]->fd, &read_set)) {
rc--;
assert(mux->descriptors[i]->callback != NULL);
mux->descriptors[i]->callback(mux_, mux->descriptors[i], MUX_EV_READ);
events = 1;
} }
if (FD_ISSET(mux->descriptors[i]->fd, &read_set)) { //need to re-check in case the callback deleted the IOMuxFD
if (mux->descriptors[i] != NULL &&
FD_ISSET(mux->descriptors[i]->fd, &write_set)) {
rc--; rc--;
events |= MUX_EV_READ; assert(mux->descriptors[i]->callback != NULL);
} mux->descriptors[i]->callback(mux_, mux->descriptors[i], MUX_EV_WRITE);
events = 1;
if (FD_ISSET(mux->descriptors[i]->fd, &write_set)) {
rc--;
events |= MUX_EV_WRITE;
} }
if (events) { event_cnt += events;
assert(mux->descriptors[i]->callback != NULL);
mux->descriptors[i]->callback(mux_, mux->descriptors[i], events);
event_cnt++;
}
} }
return event_cnt; return event_cnt;