From 4056c09e13c1aeead6dd4085fc7e263a17a0b195 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 13 Oct 2018 16:04:37 +1000 Subject: Move swaybar's event loop to common directory and refactor * The loop functions are now prefixed with `loop_`. * It is now easy to add timers to the loop. * Timers are implemented using pollfd and timerfd, rather than manually checking them when any other event happens to arrive. --- swaybar/bar.c | 17 +++--- swaybar/event_loop.c | 156 -------------------------------------------------- swaybar/meson.build | 1 - swaybar/status_line.c | 4 +- 4 files changed, 12 insertions(+), 166 deletions(-) delete mode 100644 swaybar/event_loop.c (limited to 'swaybar') diff --git a/swaybar/bar.c b/swaybar/bar.c index 9f72c94c..8e89c9a8 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -18,7 +18,6 @@ #endif #include "swaybar/bar.h" #include "swaybar/config.h" -#include "swaybar/event_loop.h" #include "swaybar/i3bar.h" #include "swaybar/ipc.h" #include "swaybar/status_line.h" @@ -26,6 +25,7 @@ #include "ipc-client.h" #include "list.h" #include "log.h" +#include "loop.h" #include "pool-buffer.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h" @@ -573,7 +573,7 @@ static void set_bar_dirty(struct swaybar *bar) { bool bar_setup(struct swaybar *bar, const char *socket_path) { bar_init(bar); - init_event_loop(); + bar->eventloop = loop_create(); bar->ipc_socketfd = ipc_open_socket(socket_path); bar->ipc_event_socketfd = ipc_open_socket(socket_path); @@ -582,6 +582,7 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) { } if (bar->config->status_command) { bar->status = status_line_init(bar->config->status_command); + bar->status->bar = bar; } bar->display = wl_display_connect(NULL); @@ -646,21 +647,23 @@ static void status_in(int fd, short mask, void *data) { if (mask & (POLLHUP | POLLERR)) { status_error(bar->status, "[error reading from status command]"); set_bar_dirty(bar); - remove_event(fd); + loop_remove_event(bar->eventloop, bar->status_event); } else if (status_handle_readable(bar->status)) { set_bar_dirty(bar); } } void bar_run(struct swaybar *bar) { - add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); - add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar); + loop_add_fd(bar->eventloop, wl_display_get_fd(bar->display), POLLIN, + display_in, bar); + loop_add_fd(bar->eventloop, bar->ipc_event_socketfd, POLLIN, ipc_in, bar); if (bar->status) { - add_event(bar->status->read_fd, POLLIN, status_in, bar); + bar->status_event = loop_add_fd( + bar->eventloop, bar->status->read_fd, POLLIN, status_in, bar); } while (1) { wl_display_flush(bar->display); - event_loop_poll(); + loop_poll(bar->eventloop); } } diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c deleted file mode 100644 index 686b9962..00000000 --- a/swaybar/event_loop.c +++ /dev/null @@ -1,156 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include -#include "swaybar/event_loop.h" -#include "list.h" - -struct event_item { - void (*cb)(int fd, short mask, void *data); - void *data; -}; - -struct timer_item { - timer_t timer; - void (*cb)(timer_t timer, void *data); - void *data; -}; - -static struct { - // The order of each must be kept consistent - struct { /* pollfd array */ - struct pollfd *items; - int capacity; - int length; - } fds; - list_t *items; /* event_item list */ - - // Timer list - list_t *timers; -} event_loop; - -void add_timer(timer_t timer, - void(*cb)(timer_t timer, void *data), - void *data) { - - struct timer_item *item = malloc(sizeof(struct timer_item)); - item->timer = timer; - item->cb = cb; - item->data = data; - - list_add(event_loop.timers, item); -} - -void add_event(int fd, short mask, - void(*cb)(int fd, short mask, void *data), void *data) { - - struct pollfd pollfd = { - fd, - mask, - 0, - }; - - // Resize - if (event_loop.fds.length == event_loop.fds.capacity) { - event_loop.fds.capacity += 10; - event_loop.fds.items = realloc(event_loop.fds.items, - sizeof(struct pollfd) * event_loop.fds.capacity); - } - - event_loop.fds.items[event_loop.fds.length++] = pollfd; - - struct event_item *item = malloc(sizeof(struct event_item)); - item->cb = cb; - item->data = data; - - list_add(event_loop.items, item); - - return; -} - -bool remove_event(int fd) { - /* - * Instead of removing events immediately, we mark them for deletion - * and clean them up later. This is so we can call remove_event inside - * an event callback safely. - */ - for (int i = 0; i < event_loop.fds.length; ++i) { - if (event_loop.fds.items[i].fd == fd) { - event_loop.fds.items[i].fd = -1; - return true; - } - } - return false; -} - -static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { - const struct timer_item *timer_item = _timer_item; - const timer_t *timer = _timer; - if (timer_item->timer == *timer) { - return 0; - } else { - return -1; - } -} -bool remove_timer(timer_t timer) { - int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); - if (index != -1) { - free(event_loop.timers->items[index]); - list_del(event_loop.timers, index); - return true; - } - return false; -} - -void event_loop_poll(void) { - poll(event_loop.fds.items, event_loop.fds.length, -1); - - for (int i = 0; i < event_loop.fds.length; ++i) { - struct pollfd pfd = event_loop.fds.items[i]; - struct event_item *item = (struct event_item *)event_loop.items->items[i]; - - // Always send these events - unsigned events = pfd.events | POLLHUP | POLLERR; - - if (pfd.revents & events) { - item->cb(pfd.fd, pfd.revents, item->data); - } - } - - // Cleanup removed events - int end = 0; - int length = event_loop.fds.length; - for (int i = 0; i < length; ++i) { - if (event_loop.fds.items[i].fd == -1) { - free(event_loop.items->items[i]); - list_del(event_loop.items, i); - --event_loop.fds.length; - } else if (end != i) { - event_loop.fds.items[end++] = event_loop.fds.items[i]; - } else { - end = i + 1; - } - } - - // check timers - // not tested, but seems to work - for (int i = 0; i < event_loop.timers->length; ++i) { - struct timer_item *item = event_loop.timers->items[i]; - int overrun = timer_getoverrun(item->timer); - if (overrun && overrun != -1) { - item->cb(item->timer, item->data); - } - } -} - -void init_event_loop(void) { - event_loop.fds.length = 0; - event_loop.fds.capacity = 10; - event_loop.fds.items = malloc( - event_loop.fds.capacity * sizeof(struct pollfd)); - event_loop.items = create_list(); - event_loop.timers = create_list(); -} diff --git a/swaybar/meson.build b/swaybar/meson.build index 7a02a33f..0c116172 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -2,7 +2,6 @@ executable( 'swaybar', [ 'bar.c', 'config.c', - 'event_loop.c', 'i3bar.c', 'ipc.c', 'main.c', diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 000609ce..3f7a386f 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -7,16 +7,16 @@ #include #include #include +#include "loop.h" #include "swaybar/bar.h" #include "swaybar/config.h" #include "swaybar/i3bar.h" -#include "swaybar/event_loop.h" #include "swaybar/status_line.h" #include "readline.h" static void status_line_close_fds(struct status_line *status) { if (status->read_fd != -1) { - remove_event(status->read_fd); + loop_remove_event(status->bar->eventloop, status->bar->status_event); close(status->read_fd); status->read_fd = -1; } -- cgit v1.2.3-54-g00ecf