Skip to content

Commit 5ed69e2

Browse files
authored
Merge pull request #48 from hook-lang/add-selectors-core-module
Add selectors core module
2 parents c0fd9a0 + b3f2d6f commit 5ed69e2

File tree

6 files changed

+545
-27
lines changed

6 files changed

+545
-27
lines changed

core/CMakeLists.txt

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -63,34 +63,40 @@ add_library(ini_mod SHARED
6363
ini.c
6464
deps/ini.c)
6565

66-
target_link_libraries(math_mod ${STATIC_LIB_TARGET})
67-
target_link_libraries(os_mod ${STATIC_LIB_TARGET})
68-
target_link_libraries(io_mod ${STATIC_LIB_TARGET})
69-
target_link_libraries(numbers_mod ${STATIC_LIB_TARGET})
70-
target_link_libraries(strings_mod ${STATIC_LIB_TARGET})
71-
target_link_libraries(arrays_mod ${STATIC_LIB_TARGET})
72-
target_link_libraries(utf8_mod ${STATIC_LIB_TARGET})
73-
target_link_libraries(hashing_mod ${STATIC_LIB_TARGET})
74-
target_link_libraries(encoding_mod ${STATIC_LIB_TARGET})
75-
target_link_libraries(socket_mod ${STATIC_LIB_TARGET})
76-
target_link_libraries(json_mod ${STATIC_LIB_TARGET})
77-
target_link_libraries(lists_mod ${STATIC_LIB_TARGET})
78-
target_link_libraries(ini_mod ${STATIC_LIB_TARGET})
66+
add_library(selectors_mod SHARED
67+
selectors.c)
68+
69+
target_link_libraries(math_mod ${STATIC_LIB_TARGET})
70+
target_link_libraries(os_mod ${STATIC_LIB_TARGET})
71+
target_link_libraries(io_mod ${STATIC_LIB_TARGET})
72+
target_link_libraries(numbers_mod ${STATIC_LIB_TARGET})
73+
target_link_libraries(strings_mod ${STATIC_LIB_TARGET})
74+
target_link_libraries(arrays_mod ${STATIC_LIB_TARGET})
75+
target_link_libraries(utf8_mod ${STATIC_LIB_TARGET})
76+
target_link_libraries(hashing_mod ${STATIC_LIB_TARGET})
77+
target_link_libraries(encoding_mod ${STATIC_LIB_TARGET})
78+
target_link_libraries(socket_mod ${STATIC_LIB_TARGET})
79+
target_link_libraries(json_mod ${STATIC_LIB_TARGET})
80+
target_link_libraries(lists_mod ${STATIC_LIB_TARGET})
81+
target_link_libraries(ini_mod ${STATIC_LIB_TARGET})
82+
target_link_libraries(selectors_mod ${STATIC_LIB_TARGET})
7983

8084
if(WIN32)
8185
target_link_libraries(socket_mod ws2_32)
86+
target_link_libraries(selectors_mod ws2_32)
8287
endif()
8388

84-
set_target_properties(math_mod PROPERTIES PREFIX "")
85-
set_target_properties(os_mod PROPERTIES PREFIX "")
86-
set_target_properties(io_mod PROPERTIES PREFIX "")
87-
set_target_properties(numbers_mod PROPERTIES PREFIX "")
88-
set_target_properties(strings_mod PROPERTIES PREFIX "")
89-
set_target_properties(arrays_mod PROPERTIES PREFIX "")
90-
set_target_properties(utf8_mod PROPERTIES PREFIX "")
91-
set_target_properties(hashing_mod PROPERTIES PREFIX "")
92-
set_target_properties(encoding_mod PROPERTIES PREFIX "")
93-
set_target_properties(socket_mod PROPERTIES PREFIX "")
94-
set_target_properties(json_mod PROPERTIES PREFIX "")
95-
set_target_properties(lists_mod PROPERTIES PREFIX "")
96-
set_target_properties(ini_mod PROPERTIES PREFIX "")
89+
set_target_properties(math_mod PROPERTIES PREFIX "")
90+
set_target_properties(os_mod PROPERTIES PREFIX "")
91+
set_target_properties(io_mod PROPERTIES PREFIX "")
92+
set_target_properties(numbers_mod PROPERTIES PREFIX "")
93+
set_target_properties(strings_mod PROPERTIES PREFIX "")
94+
set_target_properties(arrays_mod PROPERTIES PREFIX "")
95+
set_target_properties(utf8_mod PROPERTIES PREFIX "")
96+
set_target_properties(hashing_mod PROPERTIES PREFIX "")
97+
set_target_properties(encoding_mod PROPERTIES PREFIX "")
98+
set_target_properties(socket_mod PROPERTIES PREFIX "")
99+
set_target_properties(json_mod PROPERTIES PREFIX "")
100+
set_target_properties(lists_mod PROPERTIES PREFIX "")
101+
set_target_properties(ini_mod PROPERTIES PREFIX "")
102+
set_target_properties(selectors_mod PROPERTIES PREFIX "")

core/selectors.c

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
//
2+
// The Hook Programming Language
3+
// selectors.c
4+
//
5+
6+
#include "selectors.h"
7+
8+
#ifdef _WIN32
9+
#include <winsock2.h>
10+
#else
11+
#include <poll.h>
12+
#endif
13+
14+
#ifdef _WIN32
15+
#define Socket SOCKET
16+
#define PollFd WSAPOLLFD
17+
#else
18+
#define Socket int
19+
#define PollFd struct pollfd
20+
#endif
21+
22+
#define MAX_FDS (4096)
23+
24+
typedef struct
25+
{
26+
HK_USERDATA_HEADER
27+
int fld0;
28+
int fld1;
29+
int fld2;
30+
Socket sock;
31+
} SocketUserdata;
32+
33+
typedef struct
34+
{
35+
HK_USERDATA_HEADER
36+
int count;
37+
PollFd fds[MAX_FDS];
38+
SocketUserdata *udatas[MAX_FDS];
39+
} PollSelector;
40+
41+
#ifdef _WIN32
42+
static int initialized = 0;
43+
#endif
44+
45+
#ifdef _WIN32
46+
static inline void startup(void);
47+
static inline void cleanup(void);
48+
#endif
49+
50+
static inline int socket_poll(PollFd *fds, int nfds, int timeout);
51+
static inline PollSelector *poll_selector_new(void);
52+
static inline bool poll_selector_register(PollSelector *selector,
53+
SocketUserdata *udata, int events);
54+
static inline bool poll_selector_unregister(PollSelector *selector,
55+
SocketUserdata *udata);
56+
static inline bool poll_selector_modify(PollSelector *selector,
57+
SocketUserdata *udata, int events);
58+
static inline HkArray *poll_selector_poll(PollSelector *selector, int timeout);
59+
static void poll_selector_deinit(HkUserdata *udata);
60+
static void new_poll_selector_call(HkState *state, HkValue *args);
61+
static void register_call(HkState *state, HkValue *args);
62+
static void unregister_call(HkState *state, HkValue *args);
63+
static void modify_call(HkState *state, HkValue *args);
64+
static void poll_call(HkState *state, HkValue *args);
65+
66+
#ifdef _WIN32
67+
static inline void startup(void)
68+
{
69+
if (!initialized)
70+
{
71+
WSADATA wsa;
72+
(void) WSAStartup(MAKEWORD(2, 2), &wsa);
73+
}
74+
++initialized;
75+
}
76+
77+
static inline void cleanup(void)
78+
{
79+
--initialized;
80+
if (initialized) return;
81+
(void) WSACleanup();
82+
}
83+
#endif
84+
85+
static inline int socket_poll(PollFd *fds, int nfds, int timeout)
86+
{
87+
#ifdef _WIN32
88+
return WSAPoll(fds, nfds, timeout);
89+
#else
90+
return poll(fds, nfds, timeout);
91+
#endif
92+
}
93+
94+
static inline PollSelector *poll_selector_new(void)
95+
{
96+
#ifdef _WIN32
97+
startup();
98+
#endif
99+
PollSelector *selector = (PollSelector *) hk_allocate(sizeof(*selector));
100+
hk_userdata_init((HkUserdata *) selector, poll_selector_deinit);
101+
selector->count = 0;
102+
return selector;
103+
}
104+
105+
static inline bool poll_selector_register(PollSelector *selector,
106+
SocketUserdata *udata, int events)
107+
{
108+
if (selector->count == MAX_FDS) return false;
109+
PollFd fd = {
110+
.fd = (int) udata->sock,
111+
.events = events,
112+
.revents = 0
113+
};
114+
int index = selector->count;
115+
selector->fds[index] = fd;
116+
selector->udatas[index] = udata;
117+
++selector->count;
118+
return true;
119+
}
120+
121+
static inline bool poll_selector_unregister(PollSelector *selector,
122+
SocketUserdata *udata)
123+
{
124+
int i = 1;
125+
int n = selector->count;
126+
for (; i < n; ++i)
127+
{
128+
PollFd *fd = &selector->fds[i];
129+
if (fd->fd == (int) udata->sock) break;
130+
}
131+
if (i == n) return false;
132+
for (; i < n - 1; ++i)
133+
{
134+
selector->fds[i] = selector->fds[i + 1];
135+
selector->udatas[i] = selector->udatas[i + 1];
136+
}
137+
--selector->count;
138+
return true;
139+
}
140+
141+
static inline bool poll_selector_modify(PollSelector *selector,
142+
SocketUserdata *udata, int events)
143+
{
144+
int i = 1;
145+
int n = selector->count;
146+
for (; i < n; ++i)
147+
{
148+
PollFd *fd = &selector->fds[i];
149+
if (fd->fd == (int) udata->sock) break;
150+
}
151+
if (i == n) return false;
152+
selector->fds[i].events = events;
153+
return true;
154+
}
155+
156+
static inline HkArray *poll_selector_poll(PollSelector *selector, int timeout)
157+
{
158+
HkArray *arr = hk_array_new();
159+
int n = selector->count;
160+
int rc = socket_poll(selector->fds, n, timeout);
161+
if (rc == -1)
162+
{
163+
hk_array_free(arr);
164+
return NULL;
165+
}
166+
if (!rc) goto end;
167+
int j = 0;
168+
for (int i = 0; i < n && j < rc; ++i)
169+
{
170+
PollFd *fd = &selector->fds[i];
171+
int revents = fd->revents;
172+
if (!revents) continue;
173+
HkUserdata *udata = (HkUserdata *) selector->udatas[i];
174+
HkArray *event = hk_array_new_with_capacity(2);
175+
hk_array_inplace_add_element(event, hk_userdata_value(udata));
176+
hk_array_inplace_add_element(event, hk_number_value(revents));
177+
hk_array_inplace_add_element(arr, hk_array_value(event));
178+
++j;
179+
}
180+
end:
181+
return arr;
182+
}
183+
184+
static void poll_selector_deinit(HkUserdata *udata)
185+
{
186+
(void) udata;
187+
#ifdef _WIN32
188+
cleanup();
189+
#endif
190+
}
191+
192+
static void new_poll_selector_call(HkState *state, HkValue *args)
193+
{
194+
(void) args;
195+
hk_state_push_userdata(state, (HkUserdata *) poll_selector_new());
196+
}
197+
198+
static void register_call(HkState *state, HkValue *args)
199+
{
200+
hk_state_check_argument_userdata(state, args, 1);
201+
hk_return_if_not_ok(state);
202+
hk_state_check_argument_userdata(state, args, 2);
203+
hk_return_if_not_ok(state);
204+
hk_state_check_argument_int(state, args, 3);
205+
hk_return_if_not_ok(state);
206+
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
207+
SocketUserdata *udata = (SocketUserdata *) hk_as_userdata(args[2]);
208+
int events = (int) hk_as_number(args[3]);
209+
if (!poll_selector_register(selector, udata, events))
210+
{
211+
hk_state_runtime_error(state, "too many file descriptors");
212+
return;
213+
}
214+
hk_state_push_nil(state);
215+
}
216+
217+
static void unregister_call(HkState *state, HkValue *args)
218+
{
219+
hk_state_check_argument_userdata(state, args, 1);
220+
hk_return_if_not_ok(state);
221+
hk_state_check_argument_userdata(state, args, 2);
222+
hk_return_if_not_ok(state);
223+
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
224+
SocketUserdata *udata = (SocketUserdata *) hk_as_userdata(args[2]);
225+
if (!poll_selector_unregister(selector, udata))
226+
{
227+
hk_state_runtime_error(state, "file descriptor not found");
228+
return;
229+
}
230+
hk_state_push_nil(state);
231+
}
232+
233+
static void modify_call(HkState *state, HkValue *args)
234+
{
235+
hk_state_check_argument_userdata(state, args, 1);
236+
hk_return_if_not_ok(state);
237+
hk_state_check_argument_userdata(state, args, 2);
238+
hk_return_if_not_ok(state);
239+
hk_state_check_argument_int(state, args, 3);
240+
hk_return_if_not_ok(state);
241+
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
242+
SocketUserdata *udata = (SocketUserdata *) hk_as_userdata(args[2]);
243+
int events = (int) hk_as_number(args[3]);
244+
if (!poll_selector_modify(selector, udata, events))
245+
{
246+
hk_state_runtime_error(state, "file descriptor not found");
247+
return;
248+
}
249+
hk_state_push_nil(state);
250+
}
251+
252+
static void poll_call(HkState *state, HkValue *args)
253+
{
254+
hk_state_check_argument_userdata(state, args, 1);
255+
hk_return_if_not_ok(state);
256+
hk_state_check_argument_number(state, args, 2);
257+
hk_return_if_not_ok(state);
258+
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
259+
int timeout = (int) hk_as_number(args[2]);
260+
HkArray *arr = poll_selector_poll(selector, timeout);
261+
hk_state_push_array(state, arr);
262+
if (!hk_state_is_ok(state))
263+
hk_array_free(arr);
264+
}
265+
266+
HK_LOAD_MODULE_HANDLER(selectors)
267+
{
268+
hk_state_push_string_from_chars(state, -1, "selectors");
269+
hk_return_if_not_ok(state);
270+
hk_state_push_string_from_chars(state, -1, "POLLIN");
271+
hk_return_if_not_ok(state);
272+
hk_state_push_number(state, POLLIN);
273+
hk_return_if_not_ok(state);
274+
hk_state_push_string_from_chars(state, -1, "POLLOUT");
275+
hk_return_if_not_ok(state);
276+
hk_state_push_number(state, POLLOUT);
277+
hk_return_if_not_ok(state);
278+
hk_state_push_string_from_chars(state, -1, "POLLERR");
279+
hk_return_if_not_ok(state);
280+
hk_state_push_number(state, POLLERR);
281+
hk_return_if_not_ok(state);
282+
hk_state_push_string_from_chars(state, -1, "POLLHUP");
283+
hk_return_if_not_ok(state);
284+
hk_state_push_number(state, POLLHUP);
285+
hk_return_if_not_ok(state);
286+
hk_state_push_string_from_chars(state, -1, "POLLNVAL");
287+
hk_return_if_not_ok(state);
288+
hk_state_push_number(state, POLLNVAL);
289+
hk_return_if_not_ok(state);
290+
hk_state_push_string_from_chars(state, -1, "POLLPRI");
291+
hk_return_if_not_ok(state);
292+
hk_state_push_number(state, POLLPRI);
293+
hk_return_if_not_ok(state);
294+
hk_state_push_string_from_chars(state, -1, "new_poll_selector");
295+
hk_return_if_not_ok(state);
296+
hk_state_push_new_native(state, "new_poll_selector", 0, new_poll_selector_call);
297+
hk_return_if_not_ok(state);
298+
hk_state_push_string_from_chars(state, -1, "register");
299+
hk_return_if_not_ok(state);
300+
hk_state_push_new_native(state, "register", 3, register_call);
301+
hk_return_if_not_ok(state);
302+
hk_state_push_string_from_chars(state, -1, "unregister");
303+
hk_return_if_not_ok(state);
304+
hk_state_push_new_native(state, "unregister", 2, unregister_call);
305+
hk_return_if_not_ok(state);
306+
hk_state_push_string_from_chars(state, -1, "modify");
307+
hk_return_if_not_ok(state);
308+
hk_state_push_new_native(state, "modify", 3, modify_call);
309+
hk_return_if_not_ok(state);
310+
hk_state_push_string_from_chars(state, -1, "poll");
311+
hk_return_if_not_ok(state);
312+
hk_state_push_new_native(state, "poll", 2, poll_call);
313+
hk_return_if_not_ok(state);
314+
hk_state_construct(state, 11);
315+
}

core/selectors.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// The Hook Programming Language
3+
// selectors.h
4+
//
5+
6+
#ifndef SELECTORS_H
7+
#define SELECTORS_H
8+
9+
#include <hook.h>
10+
11+
HK_LOAD_MODULE_HANDLER(selectors);
12+
13+
#endif // SELECTORS_H

0 commit comments

Comments
 (0)