lph-11/odin-http/nbio/_kqueue/kqueue.odin
2025-03-13 18:14:21 +13:00

139 lines
2.9 KiB
Odin

#+build darwin
package kqueue
import "core:c"
import "core:os"
Queue_Error :: enum {
None,
Out_Of_Memory,
Descriptor_Table_Full,
File_Table_Full,
Unknown,
}
kqueue :: proc() -> (kq: os.Handle, err: Queue_Error) {
kq = os.Handle(_kqueue())
if kq == -1 {
switch os.Errno(os.get_last_error()) {
case os.ENOMEM:
err = .Out_Of_Memory
case os.EMFILE:
err = .Descriptor_Table_Full
case os.ENFILE:
err = .File_Table_Full
case:
err = .Unknown
}
}
return
}
Event_Error :: enum {
None,
Access_Denied,
Invalid_Event,
Invalid_Descriptor,
Signal,
Invalid_Timeout_Or_Filter,
Event_Not_Found,
Out_Of_Memory,
Process_Not_Found,
Unknown,
}
kevent :: proc(
kq: os.Handle,
change_list: []KEvent,
event_list: []KEvent,
timeout: ^Time_Spec,
) -> (
n_events: int,
err: Event_Error,
) {
n_events = int(
_kevent(
c.int(kq),
raw_data(change_list),
c.int(len(change_list)),
raw_data(event_list),
c.int(len(event_list)),
timeout,
),
)
if n_events == -1 {
switch os.Errno(os.get_last_error()) {
case os.EACCES:
err = .Access_Denied
case os.EFAULT:
err = .Invalid_Event
case os.EBADF:
err = .Invalid_Descriptor
case os.EINTR:
err = .Signal
case os.EINVAL:
err = .Invalid_Timeout_Or_Filter
case os.ENOENT:
err = .Event_Not_Found
case os.ENOMEM:
err = .Out_Of_Memory
case os.ESRCH:
err = .Process_Not_Found
case:
err = .Unknown
}
}
return
}
KEvent :: struct {
ident: c.uintptr_t,
filter: c.int16_t,
flags: c.uint16_t,
fflags: c.uint32_t,
data: c.intptr_t,
udata: rawptr,
}
Time_Spec :: struct {
sec: c.long,
nsec: c.long,
}
EV_ADD :: 0x0001 /* add event to kq (implies enable) */
EV_DELETE :: 0x0002 /* delete event from kq */
EV_ENABLE :: 0x0004 /* enable event */
EV_DISABLE :: 0x0008 /* disable event (not reported) */
EV_ONESHOT :: 0x0010 /* only report one occurrence */
EV_CLEAR :: 0x0020 /* clear event state after reporting */
EV_RECEIPT :: 0x0040 /* force immediate event output */
EV_DISPATCH :: 0x0080 /* disable event after reporting */
EV_UDATA_SPECIFIC :: 0x0100 /* unique kevent per udata value */
EV_FANISHED :: 0x0200 /* report that source has vanished */
EV_SYSFLAGS :: 0xF000 /* reserved by system */
EV_FLAG0 :: 0x1000 /* filter-specific flag */
EV_FLAG1 :: 0x2000 /* filter-specific flag */
EV_ERROR :: 0x4000 /* error, data contains errno */
EV_EOF :: 0x8000 /* EOF detected */
EV_DISPATCH2 :: (EV_DISPATCH | EV_UDATA_SPECIFIC)
EVFILT_READ :: -1
EVFILT_WRITE :: -2
EVFILT_AIO :: -3
EVFILT_VNODE :: -4
EVFILT_PROC :: -5
EVFILT_SIGNAL :: -6
EVFILT_TIMER :: -7
EVFILT_MACHPORT :: -8
EVFILT_FS :: -9
EVFILT_USER :: -10
EVFILT_VM :: -12
EVFILT_EXCEPT :: -15
@(default_calling_convention = "c")
foreign _ {
@(link_name = "kqueue")
_kqueue :: proc() -> c.int ---
@(link_name = "kevent")
_kevent :: proc(kq: c.int, change_list: [^]KEvent, n_changes: c.int, event_list: [^]KEvent, n_events: c.int, timeout: ^Time_Spec) -> c.int ---
}