diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 13:44:13 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 13:44:13 +0300 |
| commit | c059e3aa7f93da470f052a5cd8ee0d8dc969e679 (patch) | |
| tree | 63ffa378287ed2c606eda2e940501b9edc3d2b8b /src/common/loop.c | |
| parent | 87d0bc50d53dc216efb2b04495f090616318bc5c (diff) | |
rename and simplification
Diffstat (limited to 'src/common/loop.c')
| -rw-r--r-- | src/common/loop.c | 429 |
1 files changed, 0 insertions, 429 deletions
diff --git a/src/common/loop.c b/src/common/loop.c deleted file mode 100644 index 1c6a612..0000000 --- a/src/common/loop.c +++ /dev/null @@ -1,429 +0,0 @@ -#define _GNU_SOURCE -#define _POSIX_C_SOURCE 200809L -#include "loop.h" - -#include <errno.h> -#include <fcntl.h> -#include <poll.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#define YASL_LOOP_INIT_CAP 32 - -typedef int (*yasl_loop_fd_fn)(int fd, short revents, void *ud); - -struct yasl_fd_source { - yasl_loop_fd_fn fn; - void *ud; - int id; - int fd; - short events; -}; - -struct yasl_timer_source { - yasl_timer_cb fn; - void *ud; - uint64_t interval_ns; - uint64_t deadline_ns; - yasl_timer_id id; - bool deleted; -}; - -struct yasl_loop { - struct yasl_fd_source *fds; - struct pollfd *pollfds; - int count; - int capacity; - int next_id; - bool running; - int wake_rfd; - int wake_wfd; - int wake_watch; - - struct yasl_timer_source *timers; - int timer_count; - int timer_capacity; - uint32_t next_timer_id; - int timer_firing_depth; -}; - -uint64_t yasl_loop_now_ns(void) -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (uint64_t)ts.tv_sec * 1000000000ull + (uint64_t)ts.tv_nsec; -} - -static int loop_wake_cb(int fd, short revents, void *ud) -{ - (void)revents; - (void)ud; - char buf[128]; - ssize_t n; - while ((n = read(fd, buf, sizeof(buf))) > 0 || (n < 0 && errno == EINTR)) {} - return 0; -} - -struct yasl_loop *yasl_loop_create(void) -{ - struct yasl_loop *l = calloc(1, sizeof(*l)); - if (!l) return NULL; - - l->capacity = YASL_LOOP_INIT_CAP; - l->fds = malloc((size_t)l->capacity * sizeof(*l->fds)); - l->pollfds = malloc((size_t)l->capacity * sizeof(*l->pollfds)); - if (!l->fds || !l->pollfds) { - free(l->fds); - free(l->pollfds); - free(l); - return NULL; - } - - l->next_id = 1; - l->next_timer_id = 1; - l->wake_rfd = -1; - l->wake_wfd = -1; - - int p[2]; -#if defined(__linux__) && defined(O_CLOEXEC) - if (pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0) { - l->wake_rfd = p[0]; - l->wake_wfd = p[1]; - } -#else - if (pipe(p) == 0) { - int f0 = fcntl(p[0], F_GETFL, 0); - int f1 = fcntl(p[1], F_GETFL, 0); - if (f0 >= 0) fcntl(p[0], F_SETFL, f0 | O_NONBLOCK); - if (f1 >= 0) fcntl(p[1], F_SETFL, f1 | O_NONBLOCK); - fcntl(p[0], F_SETFD, FD_CLOEXEC); - fcntl(p[1], F_SETFD, FD_CLOEXEC); - l->wake_rfd = p[0]; - l->wake_wfd = p[1]; - } -#endif - - if (l->wake_rfd >= 0) { - l->wake_watch = yasl_loop_add_fd(l, l->wake_rfd, POLLIN, loop_wake_cb, l); - } - return l; -} - -void yasl_loop_destroy(struct yasl_loop *l) -{ - if (!l) return; - if (l->wake_watch > 0) - yasl_loop_del_fd(l, l->wake_watch); - if (l->wake_rfd >= 0) - close(l->wake_rfd); - if (l->wake_wfd >= 0) - close(l->wake_wfd); - free(l->fds); - free(l->pollfds); - free(l->timers); - free(l); -} - -int yasl_loop_add_fd(struct yasl_loop *l, int fd, short events, - int (*fn)(int fd, short revents, void *ud), void *ud) -{ - if (!l || fd < 0) - return -1; - - if (l->count >= l->capacity) { - int new_cap = l->capacity ? l->capacity * 2 : YASL_LOOP_INIT_CAP; - struct yasl_fd_source *new_fds = realloc(l->fds, (size_t)new_cap * sizeof(*new_fds)); - if (!new_fds) return -1; - l->fds = new_fds; - - struct pollfd *new_pollfds = realloc(l->pollfds, (size_t)new_cap * sizeof(*new_pollfds)); - if (!new_pollfds) return -1; - l->pollfds = new_pollfds; - l->capacity = new_cap; - } - - int id = l->next_id++; - if (l->next_id <= 0) l->next_id = 1; - - l->fds[l->count] = (struct yasl_fd_source){ - .fn = fn, .ud = ud, .id = id, .fd = fd, .events = events, - }; - l->pollfds[l->count] = (struct pollfd){ - .fd = fd, .events = events, .revents = 0, - }; - l->count++; - return id; -} - -int yasl_loop_del_fd(struct yasl_loop *l, int id) -{ - if (!l || id <= 0) return -1; - for (int i = 0; i < l->count; i++) { - if (l->fds[i].id == id) { - l->count--; - l->fds[i] = l->fds[l->count]; - l->pollfds[i] = l->pollfds[l->count]; - return 0; - } - } - return -1; -} - -int yasl_loop_set_fd_events(struct yasl_loop *l, int id, short events) -{ - if (!l || id <= 0) return -1; - for (int i = 0; i < l->count; i++) { - if (l->fds[i].id == id) { - l->fds[i].events = events; - l->pollfds[i].events = events; - return 0; - } - } - return -1; -} - -void yasl_loop_kick(struct yasl_loop *l) -{ - if (!l || l->wake_wfd < 0) return; - char b = 1; - ssize_t n; - do { - n = write(l->wake_wfd, &b, 1); - } while (n < 0 && errno == EINTR); -} - -static void timer_cleanup_deleted(struct yasl_loop *l) -{ - if (!l || l->timer_firing_depth > 0) return; - int dest = 0; - for (int src = 0; src < l->timer_count; src++) { - struct yasl_timer_source t = l->timers[src]; - l->timers[dest] = t; - dest += !t.deleted; - } - l->timer_count = dest; -} - -bool yasl_loop_timer_armed(const struct yasl_loop *l, yasl_timer_id id) -{ - if (!l || id == 0) return false; - for (int i = 0; i < l->timer_count; i++) - if (l->timers[i].id == id) - return !l->timers[i].deleted; - return false; -} - -int yasl_loop_next_timeout_ms(const struct yasl_loop *l) -{ - if (!l || l->timer_count <= 0) return -1; - uint64_t now = yasl_loop_now_ns(); - uint64_t min_deadline = UINT64_MAX; - bool has_active = false; - for (int i = 0; i < l->timer_count; i++) { - if (!l->timers[i].deleted) { - has_active = true; - if (l->timers[i].deadline_ns < min_deadline) - min_deadline = l->timers[i].deadline_ns; - } - } - if (!has_active) return -1; - if (min_deadline <= now) return 0; - uint64_t diff = min_deadline - now; - uint64_t ms = (diff + 999999ull) / 1000000ull; - return (ms > (uint64_t)INT_MAX) ? INT_MAX : (int)ms; -} - -yasl_timer_id yasl_loop_add_timer(struct yasl_loop *l, uint64_t interval_ns, - yasl_timer_cb cb, void *ud) -{ - if (!l || !cb || interval_ns == 0) return 0; - - if (l->timer_count >= l->timer_capacity) { - int new_cap = l->timer_capacity ? l->timer_capacity * 2 : 16; - struct yasl_timer_source *new_timers = realloc(l->timers, (size_t)new_cap * sizeof(*new_timers)); - if (!new_timers) return 0; - l->timers = new_timers; - l->timer_capacity = new_cap; - } - - uint32_t id = l->next_timer_id++; - if (l->next_timer_id == 0) l->next_timer_id = 1; - - uint64_t now = yasl_loop_now_ns(); - l->timers[l->timer_count++] = (struct yasl_timer_source){ - .fn = cb, - .ud = ud, - .id = id, - .interval_ns = interval_ns, - .deadline_ns = now + interval_ns, - .deleted = false, - }; - - yasl_loop_kick(l); - return id; -} - -bool yasl_loop_del_timer(struct yasl_loop *l, yasl_timer_id id) -{ - if (!l || id == 0) return false; - for (int i = l->timer_count - 1; i >= 0; i--) { - if (l->timers[i].id == id && !l->timers[i].deleted) { - l->timers[i].deleted = true; - if (l->timer_firing_depth == 0) { - if (i == l->timer_count - 1) { - while (l->timer_count > 0 && l->timers[l->timer_count - 1].deleted) - l->timer_count--; - } else { - timer_cleanup_deleted(l); - } - } - return true; - } - } - return false; -} - -int yasl_loop_step(struct yasl_loop *l, int timeout_ms) -{ - if (!l) return -1; - - int timer_to = yasl_loop_next_timeout_ms(l); - int effective_timeout = timeout_ms; - if (timer_to >= 0) { - if (effective_timeout < 0 || timer_to < effective_timeout) - effective_timeout = timer_to; - } - - if (l->count <= 0) { - if (effective_timeout > 0) { - struct timespec req = { - .tv_sec = effective_timeout / 1000, - .tv_nsec = (long)(effective_timeout % 1000) * 1000000L, - }; - nanosleep(&req, NULL); - } - } else { - int n; - do { - n = poll(l->pollfds, (nfds_t)l->count, effective_timeout); - } while (n < 0 && errno == EINTR); - - if (n < 0) return -1; - } - - int handled = 0; - - if (l->count > 0) { - int count = l->count; - struct yasl_fd_source sstack[32]; - struct pollfd pstack[32]; - struct yasl_fd_source *scopy = (count <= 32) ? sstack : malloc((size_t)count * sizeof(*scopy)); - struct pollfd *pcopy = (count <= 32) ? pstack : malloc((size_t)count * sizeof(*pcopy)); - if (!scopy || !pcopy) { - if (scopy && scopy != sstack) free(scopy); - if (pcopy && pcopy != pstack) free(pcopy); - return -1; - } - - memcpy(scopy, l->fds, (size_t)count * sizeof(*scopy)); - memcpy(pcopy, l->pollfds, (size_t)count * sizeof(*pcopy)); - - for (int i = 0; i < count; i++) { - if (pcopy[i].revents) { - short revents = pcopy[i].revents; - // Fast-path: check if source is still at index i before linear scan - bool valid = false; - if (i < l->count && l->fds[i].id == scopy[i].id) { - l->pollfds[i].revents = 0; - valid = true; - } else { - for (int j = 0; j < l->count; j++) { - if (l->fds[j].id == scopy[i].id) { - l->pollfds[j].revents = 0; - valid = true; - break; - } - } - } - if (valid && scopy[i].fn) { - scopy[i].fn(scopy[i].fd, revents, scopy[i].ud); - handled++; - } - } - } - - if (scopy != sstack) free(scopy); - if (pcopy != pstack) free(pcopy); - } - - if (l->timer_count > 0) { - uint64_t now = yasl_loop_now_ns(); - l->timer_firing_depth++; - int initial_count = l->timer_count; - for (int i = 0; i < initial_count; i++) { - if (i >= l->timer_count) break; - if (l->timers[i].deleted || l->timers[i].deadline_ns > now) - continue; - - yasl_timer_id tid = l->timers[i].id; - uint64_t interval = l->timers[i].interval_ns; - void *ud = l->timers[i].ud; - struct yasl_timer_source timer_src = l->timers[i]; - - uint64_t next_interval = timer_src.fn(ud, tid, interval); - handled++; - - // Fast-path: timer is usually still at index i unless an earlier timer was deleted - if (i < l->timer_count && l->timers[i].id == tid) { - if (next_interval == 0 || l->timers[i].deleted) { - l->timers[i].deleted = true; - } else { - l->timers[i].interval_ns = next_interval; - if (l->timers[i].deadline_ns + next_interval > now) - l->timers[i].deadline_ns += next_interval; - else - l->timers[i].deadline_ns = now + next_interval; - } - } else { - for (int j = 0; j < l->timer_count; j++) { - if (l->timers[j].id == tid) { - if (next_interval == 0 || l->timers[j].deleted) { - l->timers[j].deleted = true; - } else { - l->timers[j].interval_ns = next_interval; - if (l->timers[j].deadline_ns + next_interval > now) - l->timers[j].deadline_ns += next_interval; - else - l->timers[j].deadline_ns = now + next_interval; - } - break; - } - } - } - } - l->timer_firing_depth--; - if (l->timer_firing_depth == 0) { - timer_cleanup_deleted(l); - } - } - - return handled; -} - -int yasl_loop_run(struct yasl_loop *l) -{ - if (!l) return -1; - l->running = true; - while (l->running) { - if (yasl_loop_step(l, -1) < 0) - return -1; - } - return 0; -} - -void yasl_loop_quit(struct yasl_loop *l) -{ - if (l) l->running = false; -} |
