Rework iomux_select, so it doesn't need to deald with
dynamically allocating space for the IOMuxFD's
This commit is contained in:
+42
-61
@@ -14,54 +14,28 @@ struct IOMuxSelect {
|
||||
fd_set master_read_set;
|
||||
fd_set master_write_set;
|
||||
|
||||
struct IOMuxFD **descriptors; // array of pointers to the user IOMuxFD's
|
||||
struct IOMuxFD *descriptors[FD_SETSIZE]; // array of pointers to the user IOMuxFD's
|
||||
size_t alloc_descriptors; //allocated descriptors in 'descriptors'
|
||||
size_t num_descriptors; //number of descriptors we're watching
|
||||
size_t deleted_cnt; //used to rebuild the descriptors array
|
||||
int recalc_max;
|
||||
int max_fd; //keeps track of the max fd for select()
|
||||
};
|
||||
|
||||
static int iomux_select_update_events(struct IOMux *mux_, struct IOMuxFD *fd);
|
||||
|
||||
//grows the descriptor array. We never shrink it.
|
||||
static int iomux_select_grow(struct IOMuxSelect *mux)
|
||||
{
|
||||
void *tmp = realloc(mux->descriptors, (mux->num_descriptors + IOMUX_GROW_CHUNK) * sizeof *mux->descriptors);
|
||||
assert(tmp != NULL);
|
||||
if (tmp == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
mux->alloc_descriptors += IOMUX_GROW_CHUNK;
|
||||
mux->descriptors = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iomux_select_remove(struct IOMuxSelect *mux, size_t idx)
|
||||
{
|
||||
if (mux->num_descriptors > 1) {
|
||||
//move last element into the empty slot
|
||||
size_t last_idx = mux->num_descriptors - 1;
|
||||
mux->descriptors[idx] = mux->descriptors[last_idx];
|
||||
mux->descriptors[last_idx] = NULL;
|
||||
}
|
||||
|
||||
mux->num_descriptors--;
|
||||
}
|
||||
|
||||
static void iomux_select_rebuild(struct IOMuxSelect *mux)
|
||||
static void iomux_select_recalc_max(struct IOMuxSelect *mux)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
mux->max_fd = -1;
|
||||
|
||||
for (i = 0; i < mux->num_descriptors; ) {
|
||||
if (mux->descriptors[i] == NULL) {
|
||||
iomux_select_remove(mux, i);
|
||||
//a deleted fd slot needs to be rechecked, no i++ here
|
||||
} else {
|
||||
if (mux->descriptors[i] != NULL) {
|
||||
mux->max_fd = UC_MAX(mux->descriptors[i]->fd, mux->max_fd);
|
||||
i++;
|
||||
}
|
||||
|
||||
assert(i < FD_SETSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +44,10 @@ static int iomux_select_update_events(struct IOMux *mux_, struct IOMuxFD *fd)
|
||||
{
|
||||
struct IOMuxSelect *mux = mux_->instance;
|
||||
|
||||
if (fd->fd < 0 || fd->fd >= FD_SETSIZE) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (fd->what & MUX_EV_READ)
|
||||
FD_SET(fd->fd, &mux->master_read_set);
|
||||
else
|
||||
@@ -86,18 +64,19 @@ static int iomux_select_update_events(struct IOMux *mux_, struct IOMuxFD *fd)
|
||||
static int iomux_select_register_fd(struct IOMux *mux_, struct IOMuxFD *fd)
|
||||
{
|
||||
struct IOMuxSelect *mux = mux_->instance;
|
||||
if (fd->what == 0 || fd->callback == NULL)
|
||||
int rc;
|
||||
|
||||
if ((fd->what & MUX_EV_MASK) == 0 || fd->callback == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (mux->num_descriptors == mux->alloc_descriptors) {
|
||||
if (iomux_select_grow(mux) != 0)
|
||||
return ENOMEM;
|
||||
rc = iomux_select_update_events(mux_, fd);
|
||||
if (rc != 0) {
|
||||
return ENFILE;
|
||||
}
|
||||
|
||||
mux->descriptors[mux->num_descriptors] = fd;
|
||||
mux->descriptors[fd->fd] = fd;
|
||||
mux->num_descriptors++;
|
||||
|
||||
iomux_select_update_events(mux_, fd);
|
||||
|
||||
mux->max_fd = UC_MAX(fd->fd, mux->max_fd);
|
||||
|
||||
@@ -109,18 +88,21 @@ static int iomux_select_unregister_fd(struct IOMux *mux_, struct IOMuxFD *fd)
|
||||
struct IOMuxSelect *mux = mux_->instance;
|
||||
int rc = ENOENT;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < mux->num_descriptors; i++) {
|
||||
if (fd == mux->descriptors[i]) {
|
||||
unsigned int what = fd->what; //make sure we don't alter 'what' as seen from the user
|
||||
fd->what &= ~MUX_EV_MASK;
|
||||
iomux_select_update_events(mux_, fd);
|
||||
mux->descriptors[i] = NULL; //set the slot to NULL, the event loop needs to rebuild it.
|
||||
mux->deleted_cnt++;
|
||||
fd->what = what;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
if (fd->fd < 0 || fd->fd >= FD_SETSIZE) {
|
||||
return ENFILE;
|
||||
}
|
||||
|
||||
if (mux->descriptors[fd->fd] != NULL) {
|
||||
unsigned int what = fd->what; //make sure we don't alter 'what' as seen from the user
|
||||
|
||||
fd->what = 0;
|
||||
iomux_select_update_events(mux_, fd);
|
||||
mux->descriptors[fd->fd] = NULL;
|
||||
mux->recalc_max = 1;
|
||||
fd->what = what;
|
||||
|
||||
rc = 0;
|
||||
mux->num_descriptors--;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -136,9 +118,9 @@ static int iomux_select_run(struct IOMux *mux_, struct timeval *timeout)
|
||||
fd_set read_set;
|
||||
fd_set write_set;
|
||||
|
||||
if (mux->deleted_cnt) {
|
||||
iomux_select_rebuild(mux);
|
||||
mux->deleted_cnt = 0;
|
||||
if (mux->recalc_max) {
|
||||
iomux_select_recalc_max(mux);
|
||||
mux->recalc_max = 0;
|
||||
}
|
||||
|
||||
if (mux->max_fd == -1 && timeout == NULL)
|
||||
@@ -161,8 +143,8 @@ static int iomux_select_run(struct IOMux *mux_, struct timeval *timeout)
|
||||
if (rc == 0) //no fd's were ready, no more work to do
|
||||
return event_cnt;
|
||||
|
||||
for (i = 0; rc > 0 && i < mux->num_descriptors; i++) {
|
||||
unsigned int events = 0;
|
||||
for (i = 0; rc > 0 && i < FD_SETSIZE; i++) {
|
||||
int had_event = 0;
|
||||
|
||||
//deliver only one event at a time , to simplify application
|
||||
//programming
|
||||
@@ -171,7 +153,7 @@ static int iomux_select_run(struct IOMux *mux_, struct timeval *timeout)
|
||||
rc--;
|
||||
assert(mux->descriptors[i]->callback != NULL);
|
||||
mux->descriptors[i]->callback(mux_, mux->descriptors[i], MUX_EV_READ);
|
||||
events = 1;
|
||||
had_event = 1;
|
||||
}
|
||||
|
||||
//need to re-check in case the callback deleted the IOMuxFD
|
||||
@@ -180,10 +162,11 @@ static int iomux_select_run(struct IOMux *mux_, struct timeval *timeout)
|
||||
rc--;
|
||||
assert(mux->descriptors[i]->callback != NULL);
|
||||
mux->descriptors[i]->callback(mux_, mux->descriptors[i], MUX_EV_WRITE);
|
||||
events = 1;
|
||||
had_event = 1;
|
||||
}
|
||||
|
||||
event_cnt += events;
|
||||
event_cnt += had_event;
|
||||
|
||||
}
|
||||
|
||||
return event_cnt;
|
||||
@@ -193,8 +176,6 @@ static void iomux_select_delete(struct IOMux *mux)
|
||||
{
|
||||
if (mux != NULL && mux->instance != NULL) {
|
||||
struct IOMuxSelect *mux_select = mux->instance;
|
||||
free(mux_select->descriptors);
|
||||
mux_select->descriptors = NULL;
|
||||
free(mux_select);
|
||||
mux->instance = NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user