Skip to content

Commit

Permalink
added selectors core module
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiosvm committed Apr 1, 2024
1 parent c0fd9a0 commit b3f2d6f
Show file tree
Hide file tree
Showing 6 changed files with 545 additions and 27 deletions.
58 changes: 32 additions & 26 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,40 @@ add_library(ini_mod SHARED
ini.c
deps/ini.c)

target_link_libraries(math_mod ${STATIC_LIB_TARGET})
target_link_libraries(os_mod ${STATIC_LIB_TARGET})
target_link_libraries(io_mod ${STATIC_LIB_TARGET})
target_link_libraries(numbers_mod ${STATIC_LIB_TARGET})
target_link_libraries(strings_mod ${STATIC_LIB_TARGET})
target_link_libraries(arrays_mod ${STATIC_LIB_TARGET})
target_link_libraries(utf8_mod ${STATIC_LIB_TARGET})
target_link_libraries(hashing_mod ${STATIC_LIB_TARGET})
target_link_libraries(encoding_mod ${STATIC_LIB_TARGET})
target_link_libraries(socket_mod ${STATIC_LIB_TARGET})
target_link_libraries(json_mod ${STATIC_LIB_TARGET})
target_link_libraries(lists_mod ${STATIC_LIB_TARGET})
target_link_libraries(ini_mod ${STATIC_LIB_TARGET})
add_library(selectors_mod SHARED
selectors.c)

target_link_libraries(math_mod ${STATIC_LIB_TARGET})
target_link_libraries(os_mod ${STATIC_LIB_TARGET})
target_link_libraries(io_mod ${STATIC_LIB_TARGET})
target_link_libraries(numbers_mod ${STATIC_LIB_TARGET})
target_link_libraries(strings_mod ${STATIC_LIB_TARGET})
target_link_libraries(arrays_mod ${STATIC_LIB_TARGET})
target_link_libraries(utf8_mod ${STATIC_LIB_TARGET})
target_link_libraries(hashing_mod ${STATIC_LIB_TARGET})
target_link_libraries(encoding_mod ${STATIC_LIB_TARGET})
target_link_libraries(socket_mod ${STATIC_LIB_TARGET})
target_link_libraries(json_mod ${STATIC_LIB_TARGET})
target_link_libraries(lists_mod ${STATIC_LIB_TARGET})
target_link_libraries(ini_mod ${STATIC_LIB_TARGET})
target_link_libraries(selectors_mod ${STATIC_LIB_TARGET})

if(WIN32)
target_link_libraries(socket_mod ws2_32)
target_link_libraries(selectors_mod ws2_32)
endif()

set_target_properties(math_mod PROPERTIES PREFIX "")
set_target_properties(os_mod PROPERTIES PREFIX "")
set_target_properties(io_mod PROPERTIES PREFIX "")
set_target_properties(numbers_mod PROPERTIES PREFIX "")
set_target_properties(strings_mod PROPERTIES PREFIX "")
set_target_properties(arrays_mod PROPERTIES PREFIX "")
set_target_properties(utf8_mod PROPERTIES PREFIX "")
set_target_properties(hashing_mod PROPERTIES PREFIX "")
set_target_properties(encoding_mod PROPERTIES PREFIX "")
set_target_properties(socket_mod PROPERTIES PREFIX "")
set_target_properties(json_mod PROPERTIES PREFIX "")
set_target_properties(lists_mod PROPERTIES PREFIX "")
set_target_properties(ini_mod PROPERTIES PREFIX "")
set_target_properties(math_mod PROPERTIES PREFIX "")
set_target_properties(os_mod PROPERTIES PREFIX "")
set_target_properties(io_mod PROPERTIES PREFIX "")
set_target_properties(numbers_mod PROPERTIES PREFIX "")
set_target_properties(strings_mod PROPERTIES PREFIX "")
set_target_properties(arrays_mod PROPERTIES PREFIX "")
set_target_properties(utf8_mod PROPERTIES PREFIX "")
set_target_properties(hashing_mod PROPERTIES PREFIX "")
set_target_properties(encoding_mod PROPERTIES PREFIX "")
set_target_properties(socket_mod PROPERTIES PREFIX "")
set_target_properties(json_mod PROPERTIES PREFIX "")
set_target_properties(lists_mod PROPERTIES PREFIX "")
set_target_properties(ini_mod PROPERTIES PREFIX "")
set_target_properties(selectors_mod PROPERTIES PREFIX "")
315 changes: 315 additions & 0 deletions core/selectors.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
//
// The Hook Programming Language
// selectors.c
//

#include "selectors.h"

#ifdef _WIN32
#include <winsock2.h>
#else
#include <poll.h>
#endif

#ifdef _WIN32
#define Socket SOCKET
#define PollFd WSAPOLLFD
#else
#define Socket int
#define PollFd struct pollfd
#endif

#define MAX_FDS (4096)

typedef struct
{
HK_USERDATA_HEADER
int fld0;
int fld1;
int fld2;
Socket sock;
} SocketUserdata;

typedef struct
{
HK_USERDATA_HEADER
int count;
PollFd fds[MAX_FDS];
SocketUserdata *udatas[MAX_FDS];
} PollSelector;

#ifdef _WIN32
static int initialized = 0;
#endif

#ifdef _WIN32
static inline void startup(void);
static inline void cleanup(void);
#endif

static inline int socket_poll(PollFd *fds, int nfds, int timeout);
static inline PollSelector *poll_selector_new(void);
static inline bool poll_selector_register(PollSelector *selector,
SocketUserdata *udata, int events);
static inline bool poll_selector_unregister(PollSelector *selector,
SocketUserdata *udata);
static inline bool poll_selector_modify(PollSelector *selector,
SocketUserdata *udata, int events);
static inline HkArray *poll_selector_poll(PollSelector *selector, int timeout);
static void poll_selector_deinit(HkUserdata *udata);
static void new_poll_selector_call(HkState *state, HkValue *args);
static void register_call(HkState *state, HkValue *args);
static void unregister_call(HkState *state, HkValue *args);
static void modify_call(HkState *state, HkValue *args);
static void poll_call(HkState *state, HkValue *args);

#ifdef _WIN32
static inline void startup(void)
{
if (!initialized)
{
WSADATA wsa;
(void) WSAStartup(MAKEWORD(2, 2), &wsa);
}
++initialized;
}

static inline void cleanup(void)
{
--initialized;
if (initialized) return;
(void) WSACleanup();
}
#endif

static inline int socket_poll(PollFd *fds, int nfds, int timeout)

Check warning on line 85 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L85

Added line #L85 was not covered by tests
{
#ifdef _WIN32
return WSAPoll(fds, nfds, timeout);
#else
return poll(fds, nfds, timeout);

Check warning on line 90 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L90

Added line #L90 was not covered by tests
#endif
}

static inline PollSelector *poll_selector_new(void)

Check warning on line 94 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L94

Added line #L94 was not covered by tests
{
#ifdef _WIN32
startup();
#endif
PollSelector *selector = (PollSelector *) hk_allocate(sizeof(*selector));
hk_userdata_init((HkUserdata *) selector, poll_selector_deinit);
selector->count = 0;
return selector;

Check warning on line 102 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L99-L102

Added lines #L99 - L102 were not covered by tests
}

static inline bool poll_selector_register(PollSelector *selector,

Check warning on line 105 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L105

Added line #L105 was not covered by tests
SocketUserdata *udata, int events)
{
if (selector->count == MAX_FDS) return false;
PollFd fd = {
.fd = (int) udata->sock,

Check warning on line 110 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L108-L110

Added lines #L108 - L110 were not covered by tests
.events = events,
.revents = 0
};
int index = selector->count;
selector->fds[index] = fd;
selector->udatas[index] = udata;
++selector->count;
return true;

Check warning on line 118 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L114-L118

Added lines #L114 - L118 were not covered by tests
}

static inline bool poll_selector_unregister(PollSelector *selector,

Check warning on line 121 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L121

Added line #L121 was not covered by tests
SocketUserdata *udata)
{
int i = 1;
int n = selector->count;
for (; i < n; ++i)

Check warning on line 126 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L124-L126

Added lines #L124 - L126 were not covered by tests
{
PollFd *fd = &selector->fds[i];
if (fd->fd == (int) udata->sock) break;

Check warning on line 129 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L128-L129

Added lines #L128 - L129 were not covered by tests
}
if (i == n) return false;
for (; i < n - 1; ++i)

Check warning on line 132 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L131-L132

Added lines #L131 - L132 were not covered by tests
{
selector->fds[i] = selector->fds[i + 1];
selector->udatas[i] = selector->udatas[i + 1];

Check warning on line 135 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L134-L135

Added lines #L134 - L135 were not covered by tests
}
--selector->count;
return true;

Check warning on line 138 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L137-L138

Added lines #L137 - L138 were not covered by tests
}

static inline bool poll_selector_modify(PollSelector *selector,

Check warning on line 141 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L141

Added line #L141 was not covered by tests
SocketUserdata *udata, int events)
{
int i = 1;
int n = selector->count;
for (; i < n; ++i)

Check warning on line 146 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L144-L146

Added lines #L144 - L146 were not covered by tests
{
PollFd *fd = &selector->fds[i];
if (fd->fd == (int) udata->sock) break;

Check warning on line 149 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L148-L149

Added lines #L148 - L149 were not covered by tests
}
if (i == n) return false;
selector->fds[i].events = events;
return true;

Check warning on line 153 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L151-L153

Added lines #L151 - L153 were not covered by tests
}

static inline HkArray *poll_selector_poll(PollSelector *selector, int timeout)

Check warning on line 156 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L156

Added line #L156 was not covered by tests
{
HkArray *arr = hk_array_new();
int n = selector->count;
int rc = socket_poll(selector->fds, n, timeout);
if (rc == -1)

Check warning on line 161 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L158-L161

Added lines #L158 - L161 were not covered by tests
{
hk_array_free(arr);
return NULL;

Check warning on line 164 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L163-L164

Added lines #L163 - L164 were not covered by tests
}
if (!rc) goto end;
int j = 0;
for (int i = 0; i < n && j < rc; ++i)

Check warning on line 168 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L166-L168

Added lines #L166 - L168 were not covered by tests
{
PollFd *fd = &selector->fds[i];
int revents = fd->revents;
if (!revents) continue;
HkUserdata *udata = (HkUserdata *) selector->udatas[i];
HkArray *event = hk_array_new_with_capacity(2);
hk_array_inplace_add_element(event, hk_userdata_value(udata));
hk_array_inplace_add_element(event, hk_number_value(revents));
hk_array_inplace_add_element(arr, hk_array_value(event));
++j;

Check warning on line 178 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L170-L178

Added lines #L170 - L178 were not covered by tests
}
end:
return arr;

Check warning on line 181 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L180-L181

Added lines #L180 - L181 were not covered by tests
}

static void poll_selector_deinit(HkUserdata *udata)

Check warning on line 184 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L184

Added line #L184 was not covered by tests
{
(void) udata;
#ifdef _WIN32
cleanup();
#endif
}

static void new_poll_selector_call(HkState *state, HkValue *args)

Check warning on line 192 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L192

Added line #L192 was not covered by tests
{
(void) args;
hk_state_push_userdata(state, (HkUserdata *) poll_selector_new());

Check warning on line 195 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L195

Added line #L195 was not covered by tests
}

static void register_call(HkState *state, HkValue *args)

Check warning on line 198 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L198

Added line #L198 was not covered by tests
{
hk_state_check_argument_userdata(state, args, 1);
hk_return_if_not_ok(state);
hk_state_check_argument_userdata(state, args, 2);
hk_return_if_not_ok(state);
hk_state_check_argument_int(state, args, 3);
hk_return_if_not_ok(state);
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
SocketUserdata *udata = (SocketUserdata *) hk_as_userdata(args[2]);
int events = (int) hk_as_number(args[3]);
if (!poll_selector_register(selector, udata, events))

Check warning on line 209 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L200-L209

Added lines #L200 - L209 were not covered by tests
{
hk_state_runtime_error(state, "too many file descriptors");
return;

Check warning on line 212 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L211-L212

Added lines #L211 - L212 were not covered by tests
}
hk_state_push_nil(state);

Check warning on line 214 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L214

Added line #L214 was not covered by tests
}

static void unregister_call(HkState *state, HkValue *args)

Check warning on line 217 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L217

Added line #L217 was not covered by tests
{
hk_state_check_argument_userdata(state, args, 1);
hk_return_if_not_ok(state);
hk_state_check_argument_userdata(state, args, 2);
hk_return_if_not_ok(state);
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
SocketUserdata *udata = (SocketUserdata *) hk_as_userdata(args[2]);
if (!poll_selector_unregister(selector, udata))

Check warning on line 225 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L219-L225

Added lines #L219 - L225 were not covered by tests
{
hk_state_runtime_error(state, "file descriptor not found");
return;

Check warning on line 228 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L227-L228

Added lines #L227 - L228 were not covered by tests
}
hk_state_push_nil(state);

Check warning on line 230 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L230

Added line #L230 was not covered by tests
}

static void modify_call(HkState *state, HkValue *args)

Check warning on line 233 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L233

Added line #L233 was not covered by tests
{
hk_state_check_argument_userdata(state, args, 1);
hk_return_if_not_ok(state);
hk_state_check_argument_userdata(state, args, 2);
hk_return_if_not_ok(state);
hk_state_check_argument_int(state, args, 3);
hk_return_if_not_ok(state);
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
SocketUserdata *udata = (SocketUserdata *) hk_as_userdata(args[2]);
int events = (int) hk_as_number(args[3]);
if (!poll_selector_modify(selector, udata, events))

Check warning on line 244 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L235-L244

Added lines #L235 - L244 were not covered by tests
{
hk_state_runtime_error(state, "file descriptor not found");
return;

Check warning on line 247 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L246-L247

Added lines #L246 - L247 were not covered by tests
}
hk_state_push_nil(state);

Check warning on line 249 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L249

Added line #L249 was not covered by tests
}

static void poll_call(HkState *state, HkValue *args)

Check warning on line 252 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L252

Added line #L252 was not covered by tests
{
hk_state_check_argument_userdata(state, args, 1);
hk_return_if_not_ok(state);
hk_state_check_argument_number(state, args, 2);
hk_return_if_not_ok(state);
PollSelector *selector = (PollSelector *) hk_as_userdata(args[1]);
int timeout = (int) hk_as_number(args[2]);
HkArray *arr = poll_selector_poll(selector, timeout);
hk_state_push_array(state, arr);
if (!hk_state_is_ok(state))
hk_array_free(arr);

Check warning on line 263 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L254-L263

Added lines #L254 - L263 were not covered by tests
}

HK_LOAD_MODULE_HANDLER(selectors)

Check warning on line 266 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L266

Added line #L266 was not covered by tests
{
hk_state_push_string_from_chars(state, -1, "selectors");
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "POLLIN");
hk_return_if_not_ok(state);
hk_state_push_number(state, POLLIN);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "POLLOUT");
hk_return_if_not_ok(state);
hk_state_push_number(state, POLLOUT);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "POLLERR");
hk_return_if_not_ok(state);
hk_state_push_number(state, POLLERR);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "POLLHUP");
hk_return_if_not_ok(state);
hk_state_push_number(state, POLLHUP);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "POLLNVAL");
hk_return_if_not_ok(state);
hk_state_push_number(state, POLLNVAL);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "POLLPRI");
hk_return_if_not_ok(state);
hk_state_push_number(state, POLLPRI);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "new_poll_selector");
hk_return_if_not_ok(state);
hk_state_push_new_native(state, "new_poll_selector", 0, new_poll_selector_call);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "register");
hk_return_if_not_ok(state);
hk_state_push_new_native(state, "register", 3, register_call);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "unregister");
hk_return_if_not_ok(state);
hk_state_push_new_native(state, "unregister", 2, unregister_call);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "modify");
hk_return_if_not_ok(state);
hk_state_push_new_native(state, "modify", 3, modify_call);
hk_return_if_not_ok(state);
hk_state_push_string_from_chars(state, -1, "poll");
hk_return_if_not_ok(state);
hk_state_push_new_native(state, "poll", 2, poll_call);
hk_return_if_not_ok(state);
hk_state_construct(state, 11);

Check warning on line 314 in core/selectors.c

View check run for this annotation

Codecov / codecov/patch

core/selectors.c#L268-L314

Added lines #L268 - L314 were not covered by tests
}
13 changes: 13 additions & 0 deletions core/selectors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// The Hook Programming Language
// selectors.h
//

#ifndef SELECTORS_H
#define SELECTORS_H

#include <hook.h>

HK_LOAD_MODULE_HANDLER(selectors);

#endif // SELECTORS_H
Loading

0 comments on commit b3f2d6f

Please sign in to comment.