#include #include #include #include #include "waiter.h" struct waiter { struct waitset *set; int fd; int events; waiter_cb callback; void *arg; }; struct waitset { struct waiter **waiters; int n_waiters; struct pollfd *pollfds; int n_pollfds; }; struct waitset *waitset_create(void *ctx) { struct waitset *set = talloc_zero(ctx, struct waitset); return set; } void waitset_destroy(struct waitset *set) { talloc_free(set); } struct waiter *waiter_register(struct waitset *set, int fd, int events, waiter_cb callback, void *arg) { struct waiter **waiters, *waiter; waiters = talloc_realloc(set, set->waiters, struct waiter *, set->n_waiters + 1); if (!waiters) return NULL; set->waiters = waiters; set->n_waiters++; waiter = talloc(set->waiters, struct waiter); if (!waiter) return NULL; set->waiters[set->n_waiters - 1] = waiter; waiter->set = set; waiter->fd = fd; waiter->events = events; waiter->callback = callback; waiter->arg = arg; return waiter; } void waiter_remove(struct waiter *waiter) { struct waitset *set = waiter->set; int i; for (i = 0; i < set->n_waiters; i++) if (set->waiters[i] == waiter) break; assert(i < set->n_waiters); set->n_waiters--; memmove(&set->waiters[i], &set->waiters[i+1], (set->n_waiters - i) * sizeof(set->waiters[0])); set->waiters = talloc_realloc(set->waiters, set->waiters, struct waiter *, set->n_waiters); talloc_free(waiter); } int waiter_poll(struct waitset *set) { int i, rc; if (set->n_waiters != set->n_pollfds) { set->pollfds = talloc_realloc(set, set->pollfds, struct pollfd, set->n_waiters); set->n_pollfds = set->n_waiters; } for (i = 0; i < set->n_waiters; i++) { set->pollfds[i].fd = set->waiters[i]->fd; set->pollfds[i].events = set->waiters[i]->events; set->pollfds[i].revents = 0; } rc = poll(set->pollfds, set->n_waiters, -1); if (rc <= 0) return rc; for (i = 0; i < set->n_waiters; i++) { if (set->pollfds[i].revents) { rc = set->waiters[i]->callback(set->waiters[i]->arg); if (rc) waiter_remove(set->waiters[i]); } } return 0; }