commit 44dc0f57e75e875fc0907b5e0afd6d936ca682d1
parent 78e7d57d4b5f79651731d3a16ecf4e5a37b9d70b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Wed, 10 Aug 2022 16:49:54 +0100
epoll: Generalize event-loop example
Diffstat:
A | src/epoll.c | | | 101 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | src/timerfd.c | | | 82 | ------------------------------------------------------------------------------- |
2 files changed, 101 insertions(+), 82 deletions(-)
diff --git a/src/epoll.c b/src/epoll.c
@@ -0,0 +1,101 @@
+#include <sys/epoll.h>
+#include <sys/timerfd.h>
+#include <sys/signalfd.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+
+static int timer, signals, event_queue;
+
+static void check_err(char const* msg)
+{
+ if (errno)
+ err(1, msg);
+}
+
+static void stdin_event(void)
+{
+ char buf[64];
+ int n = read(STDIN_FILENO, buf, sizeof buf - 1);
+
+ if (n <= 0)
+ {
+ puts("Stdin closed.");
+ exit(0);
+ }
+ for (int i = 0; i < n; ++i)
+ if (iscntrl(buf[i]))
+ buf[i] = '.';
+ buf[n] = '\0';
+
+ printf("Stdin: '%s'\n", buf);
+}
+
+static void timerfd_event(void)
+{
+ static uint64_t ticks;
+ uint64_t new_ticks;
+ read(timer, &new_ticks, sizeof new_ticks);
+ ticks += new_ticks;
+ printf("Tick: +%lu %lu\n", new_ticks, ticks);
+}
+
+static void signalfd_event(void)
+{
+ struct signalfd_siginfo buf;
+ read(signals, &buf, sizeof buf);
+ check_err("read");
+ printf("Signal: %s\n", strsignal(buf.ssi_signo));
+}
+
+static void add_epollin(int fd, void(*cb)())
+{
+ epoll_ctl(event_queue, EPOLL_CTL_ADD, fd, &(struct epoll_event){
+ .events = EPOLLIN,
+ .data.ptr = cb,
+ });
+ check_err("epoll_ctl");
+}
+
+int main()
+{
+ timer = timerfd_create(CLOCK_MONOTONIC, 0);
+ check_err("timerfd_create");
+ timerfd_settime(timer, 0, &(struct itimerspec){
+ .it_interval = {1, 0}, /* Interval for periodic timer */
+ .it_value = {1, 0}, /* Initial expiration */
+ }, NULL);
+ check_err("timerfd_settime");
+
+ sigset_t sigset;
+ sigemptyset(&sigset);
+ check_err("sigemptyset");
+ sigaddset(&sigset, SIGINT);
+ check_err("sigaddset");
+ sigprocmask(SIG_SETMASK, &sigset, NULL);
+ check_err("sigprocmask");
+ signals = signalfd(-1, &sigset, 0);
+ check_err("signalfd");
+
+ event_queue = epoll_create1(0);
+ check_err("epoll_create2");
+ add_epollin(STDIN_FILENO, stdin_event);
+ add_epollin(timer, timerfd_event);
+ add_epollin(signals, signalfd_event);
+
+ for (;;)
+ {
+ struct epoll_event events[8];
+ int n_events = epoll_wait(event_queue, events, sizeof events / sizeof *events, -1);
+ check_err("epoll_wait");
+
+ for (int i = 0; i < n_events; ++i)
+ ((void(*)(void))events[i].data.ptr)();
+ }
+}
diff --git a/src/timerfd.c b/src/timerfd.c
@@ -1,82 +0,0 @@
-#include <sys/epoll.h>
-#include <sys/timerfd.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-static int timer, event_queue;
-
-static void succeed_or_die(int n, char const* msg)
-{
- if (n >= 0)
- return;
-
- perror(msg);
- exit(1);
-}
-
-static void stdin_event(void)
-{
- char buf[64];
- int n = read(STDIN_FILENO, buf, sizeof buf - 1);
-
- if (n <= 0)
- {
- puts("Stdin closed.");
- exit(0);
- }
- for (int i = 0; i < n; ++i)
- if (iscntrl(buf[i]))
- buf[i] = '.';
- buf[n] = '\0';
-
- printf("Stdin: '%s'\n", buf);
-}
-
-static void timerfd_event(void)
-{
- static uint64_t ticks;
- uint64_t new_ticks;
- read(timer, &new_ticks, sizeof new_ticks);
- ticks += new_ticks;
- printf("Tick +%lu %lu\n", new_ticks, ticks);
-}
-
-int main()
-{
- timer = timerfd_create(CLOCK_MONOTONIC, 0);
- succeed_or_die(timer, "timerfd_create");
-
- int res = timerfd_settime(timer, 0, &(struct itimerspec){
- .it_interval = {1, 0}, /* Interval for periodic timer */
- .it_value = {1, 0}, /* Initial expiration */
- }, NULL);
- succeed_or_die(res, "timerfd_settime");
-
- event_queue = epoll_create1(0);
- succeed_or_die(event_queue, "epoll_create2");
-
- res = epoll_ctl(event_queue, EPOLL_CTL_ADD, STDIN_FILENO, &(struct epoll_event){
- .events = EPOLLIN,
- .data.ptr = stdin_event,
- });
- succeed_or_die(res, "epoll_ctl");
-
- res = epoll_ctl(event_queue, EPOLL_CTL_ADD, timer, &(struct epoll_event){
- .events = EPOLLIN,
- .data.ptr = timerfd_event,
- });
- succeed_or_die(res, "epoll_ctl");
-
- for (;;)
- {
- struct epoll_event events[8];
- int n_events = epoll_wait(event_queue, events, sizeof events / sizeof *events, -1);
- succeed_or_die(n_events, "epoll_wait");
-
- for (int i = 0; i < n_events; ++i)
- ((void(*)(void))events[i].data.ptr)();
- }
-}