poller: Convert to linked_list
This commit is contained in:
parent
bbfb770c73
commit
d17632fadd
2 changed files with 79 additions and 136 deletions
|
@ -4,7 +4,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "linked_list.h"
|
||||
|
||||
/*
|
||||
* These are the event types available from the poller.
|
||||
|
@ -68,15 +68,13 @@ int event_source_signal_destroy(struct event_source_signal *event_source);
|
|||
* The poller base class. This must be created by poller_create.
|
||||
*/
|
||||
struct poller {
|
||||
struct list signals;
|
||||
struct list new_signals;
|
||||
struct list fds;
|
||||
struct list new_fds;
|
||||
struct linked_list signals;
|
||||
struct linked_list fds;
|
||||
|
||||
struct pollfd *pollfds;
|
||||
size_t pollfds_len;
|
||||
bool dirty;
|
||||
bool inpoll;
|
||||
size_t fd_event_sources;
|
||||
bool pollfds_dirty;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
203
seatd/poller.c
203
seatd/poller.c
|
@ -6,11 +6,13 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "linked_list.h"
|
||||
#include "poller.h"
|
||||
|
||||
struct event_source_fd {
|
||||
struct linked_list link; // poller::fds
|
||||
const struct event_source_fd_impl *impl;
|
||||
event_source_fd_func_t func;
|
||||
|
||||
|
@ -20,9 +22,11 @@ struct event_source_fd {
|
|||
|
||||
struct poller *poller;
|
||||
bool killed;
|
||||
ssize_t pollfd_idx;
|
||||
};
|
||||
|
||||
struct event_source_signal {
|
||||
struct linked_list link; // poller::signals
|
||||
const struct event_source_signal_impl *impl;
|
||||
event_source_signal_func_t func;
|
||||
|
||||
|
@ -40,26 +44,21 @@ struct poller *global_poller = NULL;
|
|||
void poller_init(struct poller *poller) {
|
||||
assert(global_poller == NULL);
|
||||
|
||||
list_init(&poller->fds);
|
||||
list_init(&poller->new_fds);
|
||||
list_init(&poller->signals);
|
||||
list_init(&poller->new_signals);
|
||||
linked_list_init(&poller->fds);
|
||||
linked_list_init(&poller->signals);
|
||||
poller->pollfds = NULL;
|
||||
poller->pollfds_len = 0;
|
||||
poller->fd_event_sources = 0;
|
||||
global_poller = poller;
|
||||
}
|
||||
|
||||
int poller_finish(struct poller *poller) {
|
||||
for (size_t idx = 0; idx < poller->fds.length; idx++) {
|
||||
struct event_source_fd *bpfd = poller->fds.items[idx];
|
||||
while (!linked_list_empty(&poller->fds)) {
|
||||
struct event_source_fd *bpfd = (struct event_source_fd *)poller->fds.next;
|
||||
free(bpfd);
|
||||
}
|
||||
list_free(&poller->fds);
|
||||
for (size_t idx = 0; idx < poller->new_fds.length; idx++) {
|
||||
struct event_source_fd *bpfd = poller->new_fds.items[idx];
|
||||
free(bpfd);
|
||||
}
|
||||
list_free(&poller->new_fds);
|
||||
for (size_t idx = 0; idx < poller->signals.length; idx++) {
|
||||
struct event_source_signal *bps = poller->signals.items[idx];
|
||||
while (!linked_list_empty(&poller->signals)) {
|
||||
struct event_source_signal *bps = (struct event_source_signal *)poller->signals.next;
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
|
@ -69,19 +68,6 @@ int poller_finish(struct poller *poller) {
|
|||
|
||||
free(bps);
|
||||
}
|
||||
list_free(&poller->signals);
|
||||
for (size_t idx = 0; idx < poller->new_signals.length; idx++) {
|
||||
struct event_source_signal *bps = poller->new_signals.items[idx];
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(bps->signal, &sa, NULL);
|
||||
|
||||
free(bps);
|
||||
}
|
||||
list_free(&poller->new_signals);
|
||||
free(poller->pollfds);
|
||||
return 0;
|
||||
}
|
||||
|
@ -115,24 +101,31 @@ static uint32_t poll_mask_to_event_mask(int poll_mask) {
|
|||
}
|
||||
|
||||
static int regenerate_pollfds(struct poller *poller) {
|
||||
if (poller->pollfds_len != poller->fds.length) {
|
||||
struct pollfd *fds = calloc(poller->fds.length, sizeof(struct pollfd));
|
||||
if (!poller->pollfds_dirty) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (poller->fd_event_sources > poller->pollfds_len) {
|
||||
struct pollfd *fds = calloc(poller->fd_event_sources, sizeof(struct pollfd));
|
||||
if (fds == NULL) {
|
||||
return -1;
|
||||
}
|
||||
free(poller->pollfds);
|
||||
poller->pollfds = fds;
|
||||
poller->pollfds_len = poller->fds.length;
|
||||
poller->pollfds_len = poller->fd_event_sources;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < poller->fds.length; idx++) {
|
||||
struct event_source_fd *bpfd = poller->fds.items[idx];
|
||||
poller->pollfds[idx] = (struct pollfd){
|
||||
ssize_t idx = 0;
|
||||
for (struct linked_list *elem = poller->fds.next; elem != &poller->fds; elem = elem->next) {
|
||||
struct event_source_fd *bpfd = (struct event_source_fd *)elem;
|
||||
bpfd->pollfd_idx = idx++;
|
||||
poller->pollfds[bpfd->pollfd_idx] = (struct pollfd){
|
||||
.fd = bpfd->fd,
|
||||
.events = event_mask_to_poll_mask(bpfd->mask),
|
||||
};
|
||||
}
|
||||
|
||||
poller->pollfds_dirty = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -147,31 +140,19 @@ struct event_source_fd *poller_add_fd(struct poller *poller, int fd, uint32_t ma
|
|||
bpfd->data = data;
|
||||
bpfd->func = func;
|
||||
bpfd->poller = poller;
|
||||
poller->dirty = true;
|
||||
if (poller->inpoll) {
|
||||
list_add(&poller->new_fds, bpfd);
|
||||
} else {
|
||||
list_add(&poller->fds, bpfd);
|
||||
regenerate_pollfds(poller);
|
||||
}
|
||||
bpfd->pollfd_idx = -1;
|
||||
poller->fd_event_sources += 1;
|
||||
poller->pollfds_dirty = true;
|
||||
linked_list_insert(&poller->fds, &bpfd->link);
|
||||
return (struct event_source_fd *)bpfd;
|
||||
}
|
||||
|
||||
int event_source_fd_destroy(struct event_source_fd *event_source) {
|
||||
struct event_source_fd *bpfd = (struct event_source_fd *)event_source;
|
||||
struct poller *poller = bpfd->poller;
|
||||
int idx = list_find(&poller->fds, event_source);
|
||||
if (idx == -1) {
|
||||
return -1;
|
||||
}
|
||||
poller->dirty = true;
|
||||
if (poller->inpoll) {
|
||||
bpfd->killed = true;
|
||||
} else {
|
||||
list_del(&poller->fds, idx);
|
||||
free(bpfd);
|
||||
regenerate_pollfds(poller);
|
||||
}
|
||||
poller->fd_event_sources -= 1;
|
||||
poller->pollfds_dirty = true;
|
||||
bpfd->killed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -179,11 +160,7 @@ int event_source_fd_update(struct event_source_fd *event_source, uint32_t mask)
|
|||
struct event_source_fd *bpfd = (struct event_source_fd *)event_source;
|
||||
struct poller *poller = bpfd->poller;
|
||||
event_source->mask = mask;
|
||||
|
||||
poller->dirty = true;
|
||||
if (!poller->inpoll) {
|
||||
regenerate_pollfds(poller);
|
||||
}
|
||||
poller->pollfds_dirty = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -191,9 +168,9 @@ static void signal_handler(int sig) {
|
|||
if (global_poller == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < global_poller->signals.length; idx++) {
|
||||
struct event_source_signal *bps = global_poller->signals.items[idx];
|
||||
for (struct linked_list *elem = global_poller->signals.next;
|
||||
elem != &global_poller->signals; elem = elem->next) {
|
||||
struct event_source_signal *bps = (struct event_source_signal *)elem;
|
||||
if (bps->signal == sig) {
|
||||
bps->raised = true;
|
||||
}
|
||||
|
@ -208,32 +185,18 @@ struct event_source_signal *poller_add_signal(struct poller *poller, int signal,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int refcnt = 0;
|
||||
for (size_t idx = 0; idx < poller->signals.length; idx++) {
|
||||
struct event_source_signal *bps = poller->signals.items[idx];
|
||||
if (bps->signal == signal) {
|
||||
refcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
bps->signal = signal;
|
||||
bps->data = data;
|
||||
bps->func = func;
|
||||
bps->poller = poller;
|
||||
|
||||
if (refcnt == 0) {
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = &signal_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(signal, &sa, NULL);
|
||||
}
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = &signal_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(signal, &sa, NULL);
|
||||
|
||||
if (poller->inpoll) {
|
||||
list_add(&poller->new_signals, bps);
|
||||
} else {
|
||||
list_add(&poller->signals, bps);
|
||||
}
|
||||
linked_list_insert(&poller->signals, &bps->link);
|
||||
|
||||
return (struct event_source_signal *)bps;
|
||||
}
|
||||
|
@ -242,15 +205,11 @@ int event_source_signal_destroy(struct event_source_signal *event_source) {
|
|||
struct event_source_signal *bps = (struct event_source_signal *)event_source;
|
||||
struct poller *poller = bps->poller;
|
||||
|
||||
int idx = list_find(&poller->signals, event_source);
|
||||
if (idx == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int refcnt = 0;
|
||||
for (size_t idx = 0; idx < poller->signals.length; idx++) {
|
||||
struct event_source_signal *b = poller->signals.items[idx];
|
||||
if (b->signal == bps->signal) {
|
||||
for (struct linked_list *elem = poller->signals.next; elem != &poller->signals;
|
||||
elem = elem->next) {
|
||||
struct event_source_signal *b = (struct event_source_signal *)elem;
|
||||
if (b->signal == bps->signal && !b->killed) {
|
||||
refcnt++;
|
||||
}
|
||||
}
|
||||
|
@ -263,77 +222,63 @@ int event_source_signal_destroy(struct event_source_signal *event_source) {
|
|||
sigaction(bps->signal, &sa, NULL);
|
||||
}
|
||||
|
||||
if (poller->inpoll) {
|
||||
bps->killed = true;
|
||||
} else {
|
||||
list_del(&poller->signals, idx);
|
||||
free(bps);
|
||||
}
|
||||
bps->killed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int poller_poll(struct poller *poller) {
|
||||
if (poll(poller->pollfds, poller->fds.length, -1) == -1 && errno != EINTR) {
|
||||
if (regenerate_pollfds(poller) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
poller->inpoll = true;
|
||||
if (poll(poller->pollfds, poller->fd_event_sources, -1) == -1 && errno != EINTR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < poller->fds.length; idx++) {
|
||||
short revents = poller->pollfds[idx].revents;
|
||||
for (struct linked_list *elem = poller->fds.next; elem != &poller->fds; elem = elem->next) {
|
||||
struct event_source_fd *bpfd = (struct event_source_fd *)elem;
|
||||
if (bpfd->pollfd_idx == -1 || bpfd->killed) {
|
||||
continue;
|
||||
}
|
||||
short revents = poller->pollfds[bpfd->pollfd_idx].revents;
|
||||
if (revents == 0) {
|
||||
continue;
|
||||
}
|
||||
struct event_source_fd *bpfd = poller->fds.items[idx];
|
||||
bpfd->func(poller->pollfds[idx].fd, poll_mask_to_event_mask(revents), bpfd->data);
|
||||
bpfd->func(poller->pollfds[bpfd->pollfd_idx].fd, poll_mask_to_event_mask(revents),
|
||||
bpfd->data);
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < poller->signals.length; idx++) {
|
||||
struct event_source_signal *bps = poller->signals.items[idx];
|
||||
if (!bps->raised) {
|
||||
for (struct linked_list *elem = poller->signals.next; elem != &poller->signals;
|
||||
elem = elem->next) {
|
||||
struct event_source_signal *bps = (struct event_source_signal *)elem;
|
||||
if (!bps->raised || bps->killed) {
|
||||
continue;
|
||||
}
|
||||
bps->func(bps->signal, bps->data);
|
||||
bps->raised = false;
|
||||
}
|
||||
|
||||
poller->inpoll = false;
|
||||
|
||||
for (size_t idx = 0; idx < poller->fds.length; idx++) {
|
||||
struct event_source_fd *bpfd = poller->fds.items[idx];
|
||||
for (struct linked_list *elem = poller->fds.next; elem != &poller->fds; elem = elem->next) {
|
||||
struct event_source_fd *bpfd = (struct event_source_fd *)elem;
|
||||
if (!bpfd->killed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list_del(&poller->fds, idx);
|
||||
elem = elem->prev;
|
||||
linked_list_remove(&bpfd->link);
|
||||
free(bpfd);
|
||||
idx--;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < poller->signals.length; idx++) {
|
||||
struct event_source_signal *bps = poller->signals.items[idx];
|
||||
for (struct linked_list *elem = poller->signals.next; elem != &poller->signals;
|
||||
elem = elem->next) {
|
||||
struct event_source_signal *bps = (struct event_source_signal *)elem;
|
||||
if (!bps->killed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list_del(&poller->signals, idx);
|
||||
elem = elem->prev;
|
||||
linked_list_remove(&bps->link);
|
||||
free(bps);
|
||||
idx--;
|
||||
}
|
||||
|
||||
if (poller->new_fds.length > 0) {
|
||||
list_concat(&poller->fds, &poller->new_fds);
|
||||
list_truncate(&poller->new_fds);
|
||||
}
|
||||
|
||||
if (poller->new_signals.length > 0) {
|
||||
list_concat(&poller->signals, &poller->new_signals);
|
||||
list_truncate(&poller->new_signals);
|
||||
}
|
||||
|
||||
if (poller->dirty) {
|
||||
regenerate_pollfds(poller);
|
||||
poller->dirty = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue