aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/loop.c105
-rw-r--r--common/meson.build1
2 files changed, 106 insertions, 0 deletions
diff --git a/common/loop.c b/common/loop.c
new file mode 100644
index 00000000..bfbfd5a6
--- /dev/null
+++ b/common/loop.c
@@ -0,0 +1,105 @@
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <poll.h>
+#include <sys/timerfd.h>
+#include <unistd.h>
+#include "list.h"
+#include "log.h"
+#include "loop.h"
+
+struct loop_event {
+ void (*callback)(int fd, short mask, void *data);
+ void *data;
+};
+
+struct loop {
+ struct pollfd *fds;
+ int fd_length;
+ int fd_capacity;
+
+ list_t *events; // struct loop_event
+};
+
+struct loop *loop_create(void) {
+ struct loop *loop = calloc(1, sizeof(struct loop));
+ if (!loop) {
+ wlr_log(WLR_ERROR, "Unable to allocate memory for loop");
+ return NULL;
+ }
+ loop->fd_capacity = 10;
+ loop->fds = malloc(sizeof(struct pollfd) * loop->fd_capacity);
+ loop->events = create_list();
+ return loop;
+}
+
+void loop_destroy(struct loop *loop) {
+ list_foreach(loop->events, free);
+ list_free(loop->events);
+ free(loop);
+}
+
+void loop_poll(struct loop *loop) {
+ poll(loop->fds, loop->fd_length, -1);
+
+ for (int i = 0; i < loop->fd_length; ++i) {
+ struct pollfd pfd = loop->fds[i];
+ struct loop_event *event = loop->events->items[i];
+
+ // Always send these events
+ unsigned events = pfd.events | POLLHUP | POLLERR;
+
+ if (pfd.revents & events) {
+ event->callback(pfd.fd, pfd.revents, event->data);
+ }
+ }
+}
+
+struct loop_event *loop_add_fd(struct loop *loop, int fd, short mask,
+ void (*callback)(int fd, short mask, void *data), void *data) {
+ struct pollfd pfd = {fd, mask, 0};
+
+ if (loop->fd_length == loop->fd_capacity) {
+ loop->fd_capacity += 10;
+ loop->fds = realloc(loop->fds, sizeof(struct pollfd) * loop->fd_capacity);
+ }
+
+ loop->fds[loop->fd_length++] = pfd;
+
+ struct loop_event *event = calloc(1, sizeof(struct loop_event));
+ event->callback = callback;
+ event->data = data;
+
+ list_add(loop->events, event);
+
+ return event;
+}
+
+struct loop_event *loop_add_timer(struct loop *loop, int ms,
+ void (*callback)(int fd, short mask, void *data), void *data) {
+ int fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ struct itimerspec its;
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 0;
+ its.it_value.tv_sec = ms / 1000000000;
+ its.it_value.tv_nsec = (ms * 1000000) % 1000000000;
+ timerfd_settime(fd, 0, &its, NULL);
+
+ return loop_add_fd(loop, fd, POLLIN, callback, data);
+}
+
+bool loop_remove_event(struct loop *loop, struct loop_event *event) {
+ for (int i = 0; i < loop->events->length; ++i) {
+ if (loop->events->items[i] == event) {
+ list_del(loop->events, i);
+
+ loop->fd_length--;
+ memmove(&loop->fds[i], &loop->fds[i + 1], sizeof(void*) * (loop->fd_length - i));
+
+ free(event);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/common/meson.build b/common/meson.build
index 44a29508..224a9c3f 100644
--- a/common/meson.build
+++ b/common/meson.build
@@ -5,6 +5,7 @@ lib_sway_common = static_library(
'cairo.c',
'ipc-client.c',
'log.c',
+ 'loop.c',
'list.c',
'pango.c',
'readline.c',