-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathloop_default.c.v
95 lines (84 loc) · 2.13 KB
/
loop_default.c.v
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
module picoev
$if windows {
#include <winsock2.h>
#include <ws2tcpip.h>
} $else {
#include <sys/select.h>
}
pub struct SelectLoop {
mut:
id int
now i64
}
type LoopType = SelectLoop
// create_select_loop creates a new `SelectLoop` struct with the given `id`
pub fn create_select_loop(id int) !&SelectLoop {
return &SelectLoop{
id: id
}
}
// updates the events associated with a file descriptor in the event loop
@[direct_array_access]
fn (mut pv Picoev) update_events(fd int, events int) int {
// check if fd is in range
assert fd < max_fds
pv.file_descriptors[fd].events = u32(events & picoev_readwrite)
return 0
}
// performs a single iteration of the select-based event loop
@[direct_array_access]
fn (mut pv Picoev) poll_once(max_wait_in_sec int) int {
// Initializes sets for read, write, and error events
readfds, writefds, errorfds := C.fd_set{}, C.fd_set{}, C.fd_set{}
// setup
C.FD_ZERO(&readfds)
C.FD_ZERO(&writefds)
C.FD_ZERO(&errorfds)
mut maxfd := 0
// finds the maximum file descriptor and adds sockets to the sets `fd_sets`.
for target in pv.file_descriptors {
if target.loop_id == pv.loop.id {
if target.events & picoev_read != 0 {
C.FD_SET(target.fd, &readfds)
if maxfd < target.fd {
maxfd = target.fd
}
}
if target.events & picoev_write != 0 {
C.FD_SET(target.fd, &writefds)
if maxfd < target.fd {
maxfd = target.fd
}
}
}
}
// select and handle sockets if any
tv := C.timeval{
tv_sec: u64(max_wait_in_sec)
tv_usec: 0
}
r := C.select(maxfd + 1, &readfds, &writefds, &errorfds, &tv)
if r == -1 {
// timeout
return -1
} else if r > 0 {
// Iterates through file descriptors and calls their callbacks for triggered events
for target in pv.file_descriptors {
if target.loop_id == pv.loop.id {
mut read_events := 0
if C.FD_ISSET(target.fd, &readfds) != 0 {
read_events |= picoev_read
}
if C.FD_ISSET(target.fd, &writefds) != 0 {
read_events |= picoev_write
}
if read_events != 0 {
trace_fd('do callback ${target.fd}')
// do callback!
unsafe { target.cb(target.fd, read_events, &pv) }
}
}
}
}
return 0
}