From 66572f4a9c4574c9f2a2c3ef59526ac66b807b0b Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Fri, 11 Jan 2008 21:10:37 +0100 Subject: [PATCH] Lay off the ground of our very efficient event loop. Signed-off-by: Pierre Habouzit --- lib-sys/CMakeLists.txt | 1 + lib-sys/evtloop.c | 91 ++++++++++++++++++++++++++++++++++++++++++ lib-sys/evtloop.h | 76 +++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 lib-sys/evtloop.c create mode 100644 lib-sys/evtloop.h diff --git a/lib-sys/CMakeLists.txt b/lib-sys/CMakeLists.txt index 5451b9f..178b015 100644 --- a/lib-sys/CMakeLists.txt +++ b/lib-sys/CMakeLists.txt @@ -1,6 +1,7 @@ MADMUTT_SOURCES(libsyssrc libsysgen exit.c unix.c + evtloop.c mutt_signal.c filter.c mutt_tunnel.c diff --git a/lib-sys/evtloop.c b/lib-sys/evtloop.c new file mode 100644 index 0000000..1b5d723 --- /dev/null +++ b/lib-sys/evtloop.c @@ -0,0 +1,91 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Copyright © 2006 Pierre Habouzit + */ + +#include +#include +#ifndef EPOLLRDHUP +# include +# ifdef POLLRDHUP +# define EPOLLRDHUP POLLRDHUP +# else +# define EPOLLRDHUP 0 +# endif +#endif +#include "evtloop.h" +#include "mutt.h" + +static int epollfd = -1; + +int el_job_release(job_t *w, el_status reason) +{ + w->state = EL_LLP_FINI; + if (w->m && w->m->finalize) { + w->m->finalize(w, reason); + } + if (w->fd >= 0) { + close(w->fd); + } + p_delete(&w); + return -1; +} + +int el_dispatch(int timeout) +{ + struct epoll_event events[FD_SETSIZE]; + int count = epoll_wait(epollfd, events, countof(events), timeout); + + if (count < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; + mutt_error("epoll_wait"); + mutt_exit(EXIT_FAILURE); + } + + while (--count >= 0) { + job_t *w = events[count].data.ptr; + int event = events[count].events; + int evt = 0; + + switch (w->state) { + case EL_LLP_INIT: + w->llp(w); + break; + + case EL_LLP_READY: + if (event & EPOLLRDHUP) { + IGNORE(el_job_release(w, EL_RDHUP)); + } else if (w->mode != w->emode) { + w->m->on_event(w, EL_EVT_INOUT ^ w->emode); + } else { + if (event & EPOLLIN) + evt |= EL_EVT_IN; + if (event & EPOLLOUT) + evt |= EL_EVT_OUT; + w->m->on_event(w, evt); + } + break; + + default: + IGNORE(el_job_release(w, EL_ERROR)); + break; + } + } + + return 0; +} diff --git a/lib-sys/evtloop.h b/lib-sys/evtloop.h new file mode 100644 index 0000000..f08f1e7 --- /dev/null +++ b/lib-sys/evtloop.h @@ -0,0 +1,76 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +/* + * Copyright © 2006 Pierre Habouzit + */ + +#ifndef MUTT_LIB_SYS_EVTLOOP_H +#define MUTT_LIB_SYS_EVTLOOP_H + +#include + +typedef enum el_state { + EL_LLP_INIT, + EL_LLP_READY, + EL_LLP_FINI, +} el_state; + +typedef enum el_mode { + EL_IDLE = 0, + EL_READING = 1, + EL_WRITING = 2, + EL_RDWR = 3, +} el_mode; + +typedef enum el_status { + EL_SUCCESS, + EL_ERROR, + EL_KILLED, + EL_RDHUP, +} el_status; + +typedef enum el_event { + EL_EVT_IN = EL_READING, + EL_EVT_OUT = EL_WRITING, + EL_EVT_INOUT = EL_RDWR, + EL_EVT_RUNNING = 4, + EL_EVT_WAKEUP = 5, +} el_event; + +typedef struct job_t { + int fd; + + el_state state : 2; + el_mode mode : 2; + el_mode emode : 2; + + int (*llp)(struct job_t *); + struct machine_t *m; + void *ptr; +} job_t; + +typedef struct machine_t { + const char *name; + __must_check__ int (*setup)(job_t *w, void *); + int (*on_event)(job_t *w, el_event); + void (*finalize)(job_t *w, el_status); +} machine_t; + +__must_check__ int el_job_release(job_t *j, el_status); +int el_dispatch(int timeout); + +#endif -- 2.20.1