1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#define _POSIX_C_SOURCE 200809L
#include "yasl/yasl.h"
#include <errno.h>
#include <poll.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define YASL_MAX_FDS 64
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_loop {
struct yasl_fd_source fds[YASL_MAX_FDS];
struct pollfd pollfds[YASL_MAX_FDS];
int count;
int next_id;
bool running;
};
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;
}
struct yasl_loop *yasl_loop_create(void)
{
struct yasl_loop *l = calloc(1, sizeof(*l));
if (!l) return NULL;
l->next_id = 1;
return l;
}
void yasl_loop_destroy(struct yasl_loop *l)
{
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 || l->count >= YASL_MAX_FDS || fd < 0)
return -1;
int id = l->next_id++;
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)
{
(void)l;
}
int yasl_loop_run(struct yasl_loop *l)
{
if (!l) return -1;
l->running = true;
while (l->running) {
int n = poll(l->pollfds, (nfds_t)l->count, -1);
if (n < 0) {
if (errno == EINTR) continue;
return -1;
}
for (int i = 0; i < l->count && l->running; i++) {
if (l->pollfds[i].revents) {
struct yasl_fd_source src = l->fds[i];
short revents = l->pollfds[i].revents;
l->pollfds[i].revents = 0;
if (src.fn)
src.fn(src.fd, revents, src.ud);
}
}
}
return 0;
}
void yasl_loop_quit(struct yasl_loop *l)
{
if (l) l->running = false;
}
|