maph 1.0.0 High-Performance Memory-Mapped Key-Value Database with O(1) Lookups

Loading...
Searching...
No Matches
loop.c
Go to the documentation of this file.
1/*
2 * Authored by Alex Hultman, 2018-2021.
3 * Intellectual property of third-party.
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "libusockets.h"
19#include "internal/internal.h"
20#include <stdlib.h>
21
22/* The loop has 2 fallthrough polls */
23 void us_internal_loop_data_init(struct us_loop_t *loop, void (*wakeup_cb)(struct us_loop_t *loop),
24 void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop)) {
25 loop->data.sweep_timer = us_create_timer(loop, 1, 0);
26 loop->data.recv_buf = malloc(LIBUS_RECV_BUFFER_LENGTH + LIBUS_RECV_BUFFER_PADDING * 2);
27 loop->data.ssl_data = 0;
28 loop->data.head = 0;
29 loop->data.iterator = 0;
30 loop->data.closed_head = 0;
31 loop->data.low_prio_head = 0;
32 loop->data.low_prio_budget = 0;
33
34 loop->data.pre_cb = pre_cb;
35 loop->data.post_cb = post_cb;
36 loop->data.iteration_nr = 0;
37
38 loop->data.wakeup_async = us_internal_create_async(loop, 1, 0);
39 us_internal_async_set(loop->data.wakeup_async, (void (*)(struct us_internal_async *)) wakeup_cb);
40}
41
42 void us_internal_loop_data_free(struct us_loop_t *loop) {
43#ifndef LIBUS_NO_SSL
44 us_internal_free_loop_ssl_data(loop);
45#endif
46
47 free(loop->data.recv_buf);
48
49 us_timer_close(loop->data.sweep_timer);
50 us_internal_async_close(loop->data.wakeup_async);
51}
52
53 void us_wakeup_loop(struct us_loop_t *loop) {
54 us_internal_async_wakeup(loop->data.wakeup_async);
55}
56
57 void us_internal_loop_link(struct us_loop_t *loop, struct us_socket_context_t *context) {
58 /* Insert this context as the head of loop */
59 context->next = loop->data.head;
60 context->prev = 0;
61 if (loop->data.head) {
62 loop->data.head->prev = context;
63 }
64 loop->data.head = context;
65}
66
67/* Unlink is called before free */
68 void us_internal_loop_unlink(struct us_loop_t *loop, struct us_socket_context_t *context) {
69 if (loop->data.head == context) {
70 loop->data.head = context->next;
71 if (loop->data.head) {
72 loop->data.head->prev = 0;
73 }
74 } else {
75 context->prev->next = context->next;
76 if (context->next) {
77 context->next->prev = context->prev;
78 }
79 }
80}
81
82/* This functions should never run recursively */
83 void us_internal_timer_sweep(struct us_loop_t *loop) {
84 struct us_internal_loop_data_t *loop_data = &loop->data;
85 /* For all socket contexts in this loop */
86 for (loop_data->iterator = loop_data->head; loop_data->iterator; loop_data->iterator = loop_data->iterator->next) {
87
88 struct us_socket_context_t *context = loop_data->iterator;
89
90 /* Update this context's timestamps (this could be moved to loop and done once) */
91 context->global_tick++;
92 unsigned char short_ticks = context->timestamp = context->global_tick % 240;
93 unsigned char long_ticks = context->long_timestamp = (context->global_tick / 15) % 240;
94
95 /* Begin at head */
96 struct us_socket_t *s = context->head_sockets;
97 while (s) {
98 /* Seek until end or timeout found (tightest loop) */
99 while (1) {
100 /* We only read from 1 random cache line here */
101 if (short_ticks == s->timeout || long_ticks == s->long_timeout) {
102 break;
103 }
104
105 /* Did we reach the end without a find? */
106 if ((s = s->next) == 0) {
107 goto next_context;
108 }
109 }
110
111 /* Here we have a timeout to emit (slow path) */
112 context->iterator = s;
113
114 if (short_ticks == s->timeout) {
115 s->timeout = 255;
116 context->on_socket_timeout(s);
117 }
118
119 if (context->iterator == s && long_ticks == s->long_timeout) {
120 s->long_timeout = 255;
121 context->on_socket_long_timeout(s);
122 }
123
124 /* Check for unlink / link (if the event handler did not modify the chain, we step 1) */
125 if (s == context->iterator) {
126 s = s->next;
127 } else {
128 /* The iterator was changed by event handler */
129 s = context->iterator;
130 }
131 }
132 /* We always store a 0 to context->iterator here since we are no longer iterating this context */
133 next_context:
134 context->iterator = 0;
135 }
136}
137
138/* We do not want to block the loop with tons and tons of CPU-intensive work for SSL handshakes.
139 * Spread it out during many loop iterations, prioritizing already open connections, they are far
140 * easier on CPU */
141 static const int MAX_LOW_PRIO_SOCKETS_PER_LOOP_ITERATION = 5;
142
143 void us_internal_handle_low_priority_sockets(struct us_loop_t *loop) {
144 struct us_internal_loop_data_t *loop_data = &loop->data;
145 struct us_socket_t *s;
146
147 loop_data->low_prio_budget = MAX_LOW_PRIO_SOCKETS_PER_LOOP_ITERATION;
148
149 for (s = loop_data->low_prio_head; s && loop_data->low_prio_budget > 0; s = loop_data->low_prio_head, loop_data->low_prio_budget--) {
150 /* Unlink this socket from the low-priority queue */
151 loop_data->low_prio_head = s->next;
152 if (s->next) s->next->prev = 0;
153 s->next = 0;
154
155 us_internal_socket_context_link_socket(s->context, s);
156 us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) | LIBUS_SOCKET_READABLE);
157
158 s->low_prio_state = 2;
159 }
160}
161
162/* Note: Properly takes the linked list and timeout sweep into account */
163 void us_internal_free_closed_sockets(struct us_loop_t *loop) {
164 /* Free all closed sockets (maybe it is better to reverse order?) */
165 if (loop->data.closed_head) {
166 for (struct us_socket_t *s = loop->data.closed_head; s; ) {
167 struct us_socket_t *next = s->next;
168 us_poll_free((struct us_poll_t *) s, loop);
169 s = next;
170 }
171 loop->data.closed_head = 0;
172 }
173}
174
175 void sweep_timer_cb(struct us_internal_callback_t *cb) {
176 us_internal_timer_sweep(cb->loop);
177}
178
179 long long us_loop_iteration_number(struct us_loop_t *loop) {
180 return loop->data.iteration_nr;
181}
182
183/* These may have somewhat different meaning depending on the underlying event library */
184 void us_internal_loop_pre(struct us_loop_t *loop) {
185 loop->data.iteration_nr++;
186 us_internal_handle_low_priority_sockets(loop);
187 loop->data.pre_cb(loop);
188}
189
190 void us_internal_loop_post(struct us_loop_t *loop) {
191 us_internal_free_closed_sockets(loop);
192 loop->data.post_cb(loop);
193}
194
195 void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int events) {
196 switch (us_internal_poll_type(p)) {
197 case POLL_TYPE_CALLBACK: {
198 struct us_internal_callback_t *cb = (struct us_internal_callback_t *) p;
199 /* Timers, asyncs should accept (read), while UDP sockets should obviously not */
200 if (!cb->leave_poll_ready) {
201 /* Let's just have this macro to silence the CodeQL alert regarding empty function when using libuv */
202 #ifndef LIBUS_USE_LIBUV
203 us_internal_accept_poll_event(p);
204 #endif
205 }
206 cb->cb(cb->cb_expects_the_loop ? (struct us_internal_callback_t *) cb->loop : (struct us_internal_callback_t *) &cb->p);
207 }
208 break;
209 case POLL_TYPE_SEMI_SOCKET: {
210 /* Both connect and listen sockets are semi-sockets
211 * but they poll for different events */
212 if (us_poll_events(p) == LIBUS_SOCKET_WRITABLE) {
213 struct us_socket_t *s = (struct us_socket_t *) p;
214
215 /* It is perfectly possible to come here with an error */
216 if (error) {
217 /* Emit error, close without emitting on_close */
218 s->context->on_connect_error(s, 0);
219 us_socket_close_connecting(0, s);
220 } else {
221 /* All sockets poll for readable */
222 us_poll_change(p, s->context->loop, LIBUS_SOCKET_READABLE);
223
224 /* We always use nodelay */
225 bsd_socket_nodelay(us_poll_fd(p), 1);
226
227 /* We are now a proper socket */
228 us_internal_poll_set_type(p, POLL_TYPE_SOCKET);
229
230 /* If we used a connection timeout we have to reset it here */
231 us_socket_timeout(0, s, 0);
232
233 s->context->on_open(s, 1, 0, 0);
234 }
235 } else {
236 struct us_listen_socket_t *listen_socket = (struct us_listen_socket_t *) p;
237 struct bsd_addr_t addr;
238
239 LIBUS_SOCKET_DESCRIPTOR client_fd = bsd_accept_socket(us_poll_fd(p), &addr);
240 if (client_fd == LIBUS_SOCKET_ERROR) {
241 /* Todo: start timer here */
242
243 } else {
244
245 /* Todo: stop timer if any */
246
247 do {
248 struct us_poll_t *accepted_p = us_create_poll(us_socket_context(0, &listen_socket->s)->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + listen_socket->socket_ext_size);
249 us_poll_init(accepted_p, client_fd, POLL_TYPE_SOCKET);
250 us_poll_start(accepted_p, listen_socket->s.context->loop, LIBUS_SOCKET_READABLE);
251
252 struct us_socket_t *s = (struct us_socket_t *) accepted_p;
253
254 s->context = listen_socket->s.context;
255 s->timeout = 255;
256 s->long_timeout = 255;
257 s->low_prio_state = 0;
258
259 /* We always use nodelay */
260 bsd_socket_nodelay(client_fd, 1);
261
262 us_internal_socket_context_link_socket(listen_socket->s.context, s);
263
264 listen_socket->s.context->on_open(s, 0, bsd_addr_get_ip(&addr), bsd_addr_get_ip_length(&addr));
265
266 /* Exit accept loop if listen socket was closed in on_open handler */
267 if (us_socket_is_closed(0, &listen_socket->s)) {
268 break;
269 }
270
271 } while ((client_fd = bsd_accept_socket(us_poll_fd(p), &addr)) != LIBUS_SOCKET_ERROR);
272 }
273 }
274 }
275 break;
276 case POLL_TYPE_SOCKET_SHUT_DOWN:
277 case POLL_TYPE_SOCKET: {
278 /* We should only use s, no p after this point */
279 struct us_socket_t *s = (struct us_socket_t *) p;
280
281 /* Such as epollerr epollhup */
282 if (error) {
283 /* Todo: decide what code we give here */
284 s = us_socket_close(0, s, 0, NULL);
285 return;
286 }
287
288 if (events & LIBUS_SOCKET_WRITABLE) {
289 /* Note: if we failed a write as a socket of one loop then adopted
290 * to another loop, this will be wrong. Absurd case though */
291 s->context->loop->data.last_write_failed = 0;
292
293 s = s->context->on_writable(s);
294
295 if (us_socket_is_closed(0, s)) {
296 return;
297 }
298
299 /* If we have no failed write or if we shut down, then stop polling for more writable */
300 if (!s->context->loop->data.last_write_failed || us_socket_is_shut_down(0, s)) {
301 us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) & LIBUS_SOCKET_READABLE);
302 }
303 }
304
305 if (events & LIBUS_SOCKET_READABLE) {
306 /* Contexts may prioritize down sockets that are currently readable, e.g. when SSL handshake has to be done.
307 * SSL handshakes are CPU intensive, so we limit the number of handshakes per loop iteration, and move the rest
308 * to the low-priority queue */
309 if (s->context->is_low_prio(s)) {
310 if (s->low_prio_state == 2) {
311 s->low_prio_state = 0; /* Socket has been delayed and now it's time to process incoming data for one iteration */
312 } else if (s->context->loop->data.low_prio_budget > 0) {
313 s->context->loop->data.low_prio_budget--; /* Still having budget for this iteration - do normal processing */
314 } else {
315 us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) & LIBUS_SOCKET_WRITABLE);
316 us_internal_socket_context_unlink_socket(s->context, s);
317
318 /* Link this socket to the low-priority queue - we use a LIFO queue, to prioritize newer clients that are
319 * maybe not already timeouted - sounds unfair, but works better in real-life with smaller client-timeouts
320 * under high load */
321 s->prev = 0;
322 s->next = s->context->loop->data.low_prio_head;
323 if (s->next) s->next->prev = s;
324 s->context->loop->data.low_prio_head = s;
325
326 s->low_prio_state = 1;
327
328 break;
329 }
330 }
331
332 int length = bsd_recv(us_poll_fd(&s->p), s->context->loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, LIBUS_RECV_BUFFER_LENGTH, 0);
333 if (length > 0) {
334 s = s->context->on_data(s, s->context->loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, length);
335 } else if (!length) {
336 if (us_socket_is_shut_down(0, s)) {
337 /* We got FIN back after sending it */
338 /* Todo: We should give "CLEAN SHUTDOWN" as reason here */
339 s = us_socket_close(0, s, 0, NULL);
340 } else {
341 /* We got FIN, so stop polling for readable */
342 us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) & LIBUS_SOCKET_WRITABLE);
343 s = s->context->on_end(s);
344 }
345 } else if (length == LIBUS_SOCKET_ERROR && !bsd_would_block()) {
346 /* Todo: decide also here what kind of reason we should give */
347 s = us_socket_close(0, s, 0, NULL);
348 }
349 }
350 }
351 break;
352 }
353}
354
355/* Integration only requires the timer to be set up */
356 void us_loop_integrate(struct us_loop_t *loop) {
357 us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000);
358}
359
360 void *us_loop_ext(struct us_loop_t *loop) {
361 return loop + 1;
362}
LIBUS_SOCKET_WRITABLE
#define LIBUS_SOCKET_WRITABLE
Definition asio.h:24
LIBUS_SOCKET_READABLE
#define LIBUS_SOCKET_READABLE
Definition asio.h:23
bsd_recv
int bsd_recv(int fd, void *buf, int length, int flags)
Definition bsd.c:396
bsd_addr_get_ip
char * bsd_addr_get_ip(struct bsd_addr_t *addr)
Definition bsd.c:360
bsd_addr_get_ip_length
int bsd_addr_get_ip_length(struct bsd_addr_t *addr)
Definition bsd.c:364
bsd_socket_nodelay
void bsd_socket_nodelay(int fd, int enabled)
Definition bsd.c:278
bsd_accept_socket
int bsd_accept_socket(int fd, struct bsd_addr_t *addr)
Definition bsd.c:373
bsd_would_block
int bsd_would_block()
Definition bsd.c:422
LIBUS_SOCKET_ERROR
#define LIBUS_SOCKET_ERROR
Definition bsd.h:44
bsd_addr_t
Definition bsd.h:50
us_internal_socket_context_unlink_socket
void us_internal_socket_context_unlink_socket(struct us_socket_context_t *context, struct us_socket_t *s)
Definition context.c:89
us_internal_socket_context_link_socket
void us_internal_socket_context_link_socket(struct us_socket_context_t *context, struct us_socket_t *s)
Definition context.c:121
internal.h
us_internal_poll_set_type
void us_internal_poll_set_type(struct us_poll_t *p, int poll_type)
us_internal_async_wakeup
void us_internal_async_wakeup(struct us_internal_async *a)
us_listen_socket_t::s
struct us_socket_t s
Definition internal.h:109
us_socket_t::p
struct us_poll_t p
Definition internal.h:90
us_internal_async_set
void us_internal_async_set(struct us_internal_async *a, void(*cb)(struct us_internal_async *))
us_socket_t::long_timeout
unsigned char long_timeout
Definition internal.h:92
us_socket_t::next
struct us_socket_t * next
Definition internal.h:95
us_internal_async_close
void us_internal_async_close(struct us_internal_async *a)
us_socket_t::timeout
unsigned char timeout
Definition internal.h:91
us_internal_create_async
struct us_internal_async * us_internal_create_async(struct us_loop_t *loop, int fallthrough, unsigned int ext_size)
us_socket_t::prev
struct us_socket_t * prev
Definition internal.h:95
us_internal_poll_type
int us_internal_poll_type(struct us_poll_t *p)
us_socket_t::low_prio_state
unsigned short low_prio_state
Definition internal.h:93
us_socket_t::context
struct us_socket_context_t * context
Definition internal.h:94
us_internal_free_loop_ssl_data
void us_internal_free_loop_ssl_data(struct us_loop_t *loop)
us_listen_socket_t::socket_ext_size
unsigned int socket_ext_size
Definition internal.h:110
POLL_TYPE_CALLBACK
@ POLL_TYPE_CALLBACK
Definition internal.h:50
POLL_TYPE_SEMI_SOCKET
@ POLL_TYPE_SEMI_SOCKET
Definition internal.h:49
POLL_TYPE_SOCKET
@ POLL_TYPE_SOCKET
Definition internal.h:47
POLL_TYPE_SOCKET_SHUT_DOWN
@ POLL_TYPE_SOCKET_SHUT_DOWN
Definition internal.h:48
us_internal_accept_poll_event
unsigned int us_internal_accept_poll_event(struct us_poll_t *p)
us_listen_socket_t
Definition internal.h:108
us_socket_t
Definition internal.h:89
libusockets.h
us_create_timer
struct us_timer_t * us_create_timer(struct us_loop_t *loop, int fallthrough, unsigned int ext_size)
us_poll_init
void us_poll_init(struct us_poll_t *p, int fd, int poll_type)
LIBUS_SOCKET_DESCRIPTOR
#define LIBUS_SOCKET_DESCRIPTOR
Definition libusockets.h:38
us_create_poll
struct us_poll_t * us_create_poll(struct us_loop_t *loop, int fallthrough, unsigned int ext_size)
us_socket_close_connecting
struct us_socket_t * us_socket_close_connecting(int ssl, struct us_socket_t *s)
Definition socket.c:86
us_poll_change
void us_poll_change(struct us_poll_t *p, struct us_loop_t *loop, int events)
us_poll_fd
int us_poll_fd(struct us_poll_t *p)
LIBUS_TIMEOUT_GRANULARITY
#define LIBUS_TIMEOUT_GRANULARITY
Definition libusockets.h:24
us_socket_is_shut_down
int us_socket_is_shut_down(int ssl, struct us_socket_t *s)
Definition socket.c:177
us_poll_events
int us_poll_events(struct us_poll_t *p)
us_timer_close
void us_timer_close(struct us_timer_t *timer)
us_socket_context
struct us_socket_context_t * us_socket_context(int ssl, struct us_socket_t *s)
Definition socket.c:50
us_socket_close
struct us_socket_t * us_socket_close(int ssl, struct us_socket_t *s, int code, void *reason)
Definition socket.c:105
us_poll_free
void us_poll_free(struct us_poll_t *p, struct us_loop_t *loop)
LIBUS_RECV_BUFFER_LENGTH
#define LIBUS_RECV_BUFFER_LENGTH
Definition libusockets.h:22
LIBUS_RECV_BUFFER_PADDING
#define LIBUS_RECV_BUFFER_PADDING
Definition libusockets.h:26
us_socket_timeout
void us_socket_timeout(int ssl, struct us_socket_t *s, unsigned int seconds)
Definition socket.c:54
us_poll_start
void us_poll_start(struct us_poll_t *p, struct us_loop_t *loop, int events)
us_timer_set
void us_timer_set(struct us_timer_t *timer, void(*cb)(struct us_timer_t *t), int ms, int repeat_ms)
us_socket_is_closed
int us_socket_is_closed(int ssl, struct us_socket_t *s)
Definition socket.c:76
us_loop_t::data
struct us_internal_loop_data_t data
Definition asio.h:27
us_poll_t
Definition asio.h:37
us_loop_t
Definition asio.h:26
us_loop_iteration_number
long long us_loop_iteration_number(struct us_loop_t *loop)
Definition loop.c:179
sweep_timer_cb
void sweep_timer_cb(struct us_internal_callback_t *cb)
Definition loop.c:175
us_internal_loop_unlink
void us_internal_loop_unlink(struct us_loop_t *loop, struct us_socket_context_t *context)
Definition loop.c:68
us_wakeup_loop
void us_wakeup_loop(struct us_loop_t *loop)
Definition loop.c:53
us_internal_timer_sweep
void us_internal_timer_sweep(struct us_loop_t *loop)
Definition loop.c:83
us_internal_handle_low_priority_sockets
void us_internal_handle_low_priority_sockets(struct us_loop_t *loop)
Definition loop.c:143
us_internal_loop_post
void us_internal_loop_post(struct us_loop_t *loop)
Definition loop.c:190
us_internal_loop_data_free
void us_internal_loop_data_free(struct us_loop_t *loop)
Definition loop.c:42
us_internal_loop_link
void us_internal_loop_link(struct us_loop_t *loop, struct us_socket_context_t *context)
Definition loop.c:57
us_internal_loop_pre
void us_internal_loop_pre(struct us_loop_t *loop)
Definition loop.c:184
us_loop_ext
void * us_loop_ext(struct us_loop_t *loop)
Definition loop.c:360
MAX_LOW_PRIO_SOCKETS_PER_LOOP_ITERATION
static const int MAX_LOW_PRIO_SOCKETS_PER_LOOP_ITERATION
Definition loop.c:141
us_internal_dispatch_ready_poll
void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int events)
Definition loop.c:195
us_loop_integrate
void us_loop_integrate(struct us_loop_t *loop)
Definition loop.c:356
us_internal_free_closed_sockets
void us_internal_free_closed_sockets(struct us_loop_t *loop)
Definition loop.c:163
us_internal_loop_data_init
void us_internal_loop_data_init(struct us_loop_t *loop, void(*wakeup_cb)(struct us_loop_t *loop), void(*pre_cb)(struct us_loop_t *loop), void(*post_cb)(struct us_loop_t *loop))
Definition loop.c:23
us_internal_callback_t
Definition internal.h:99
us_internal_callback_t::loop
struct us_loop_t * loop
Definition internal.h:101
us_internal_callback_t::cb
void(* cb)(struct us_internal_callback_t *cb)
Definition internal.h:104
us_internal_callback_t::p
struct us_poll_t p
Definition internal.h:100
us_internal_loop_data_t
Definition loop_data.h:21
us_internal_loop_data_t::ssl_data
void * ssl_data
Definition loop_data.h:28
us_internal_loop_data_t::wakeup_async
struct us_internal_async * wakeup_async
Definition loop_data.h:23
us_internal_loop_data_t::recv_buf
char * recv_buf
Definition loop_data.h:27
us_internal_loop_data_t::low_prio_head
struct us_socket_t * low_prio_head
Definition loop_data.h:32
us_internal_loop_data_t::head
struct us_socket_context_t * head
Definition loop_data.h:25
us_internal_loop_data_t::low_prio_budget
int low_prio_budget
Definition loop_data.h:33
us_internal_loop_data_t::post_cb
void(* post_cb)(struct us_loop_t *)
Definition loop_data.h:30
us_internal_loop_data_t::sweep_timer
struct us_timer_t * sweep_timer
Definition loop_data.h:22
us_internal_loop_data_t::closed_head
struct us_socket_t * closed_head
Definition loop_data.h:31
us_internal_loop_data_t::iterator
struct us_socket_context_t * iterator
Definition loop_data.h:26
us_internal_loop_data_t::last_write_failed
int last_write_failed
Definition loop_data.h:24
us_internal_loop_data_t::pre_cb
void(* pre_cb)(struct us_loop_t *)
Definition loop_data.h:29
us_internal_loop_data_t::iteration_nr
long long iteration_nr
Definition loop_data.h:35
us_socket_context_t
Definition internal.h:117
us_socket_context_t::on_end
struct us_socket_t *(* on_end)(struct us_socket_t *)
Definition internal.h:134
us_socket_context_t::head_sockets
struct us_socket_t * head_sockets
Definition internal.h:122
us_socket_context_t::long_timestamp
unsigned char long_timestamp
Definition internal.h:121
us_socket_context_t::timestamp
unsigned char timestamp
Definition internal.h:120
us_socket_context_t::is_low_prio
int(* is_low_prio)(struct us_socket_t *)
Definition internal.h:136
us_socket_context_t::loop
struct us_loop_t * loop
Definition internal.h:118
us_socket_context_t::prev
struct us_socket_context_t * prev
Definition internal.h:125
us_socket_context_t::on_data
struct us_socket_t *(* on_data)(struct us_socket_t *, char *data, int length)
Definition internal.h:128
us_socket_context_t::on_socket_timeout
struct us_socket_t *(* on_socket_timeout)(struct us_socket_t *)
Definition internal.h:132
us_socket_context_t::on_socket_long_timeout
struct us_socket_t *(* on_socket_long_timeout)(struct us_socket_t *)
Definition internal.h:133
us_socket_context_t::iterator
struct us_socket_t * iterator
Definition internal.h:124
us_socket_context_t::on_writable
struct us_socket_t *(* on_writable)(struct us_socket_t *)
Definition internal.h:129
us_socket_context_t::on_open
struct us_socket_t *(* on_open)(struct us_socket_t *, int is_client, char *ip, int ip_length)
Definition internal.h:127
us_socket_context_t::on_connect_error
struct us_socket_t *(* on_connect_error)(struct us_socket_t *, int code)
Definition internal.h:135
us_socket_context_t::next
struct us_socket_context_t * next
Definition internal.h:125
us_socket_context_t::global_tick
uint32_t global_tick
Definition internal.h:119