package nbio implements a non-blocking I/O and event loop abstraction layer over several platform-specific asynchronous I/O APIs. More examples can be found in Odin's examples repository at [[ examples/nbio ; https://github.com/odin-lang/examples/tree/master/nbio ]]. **Event Loop**: Each thread may have at most one event loop associated with it. This is enforced by the package, as running multiple event loops on a single thread does not make sense. Event loops are reference counted and managed by the package. `acquire_thread_event_loop` and `release_thread_event_loop` can be used to acquire and release a reference. Acquiring must be done before any operation is done. The event loop progresses in ticks. A tick checks if any work is to be done, and based on the given timeout may block waiting for work. Ticks are typically done using the `tick`, `run`, and `run_until` procedures. Example: package main import "core:nbio" import "core:time" import "core:fmt" main :: proc() { err := nbio.acquire_thread_event_loop() assert(err == nil) defer nbio.release_thread_event_loop() nbio.timeout(time.Second, proc(_: ^nbio.Operation) { fmt.println("Hellope after 1 second!") }) err = nbio.run() assert(err == nil) } **Time and timeouts**: Timeouts are intentionally *slightly inaccurate* by design. A timeout is not checked continuously, instead, it is evaluated only when a tick occurs. This means if a tick took a long time, your timeout may be ready for a bit of time already before the callback is called. The function `now` returns the current time as perceived by the event loop. This value is cached at least once per tick so it is fast to retrieve. Most operations also take an optional timeout when executed. If the timeout completes before the operation, the operation is cancelled and called back with a `.Timeout` error. **Threading**: The package has a concept of I/O threads (threads that are ticking) and worker threads (any other thread). An I/O thread is mostly self contained, operations are executed on it, and callbacks run on it. If you try to execute an operation on a thread that has no running event loop a panic will be executed. Instead a worker thread can execute operations onto a running event loop by taking it's reference and executing operations with that reference. In this case: - The operation is enqueued from the worker thread - The I/O thread is optionally woken up from blocking for work with `wake_up` - The next tick, the operation is executed by the I/O thread - The callback is invoked on the I/O thread Example: package main import "core:nbio" import "core:net" import "core:thread" import "core:time" Connection :: struct { loop: ^nbio.Event_Loop, socket: net.TCP_Socket, } main :: proc() { workers: thread.Pool thread.pool_init(&workers, context.allocator, 2) thread.pool_start(&workers) err := nbio.acquire_thread_event_loop() defer nbio.release_thread_event_loop() assert(err == nil) server, listen_err := nbio.listen_tcp({nbio.IP4_Any, 1234}) assert(listen_err == nil) nbio.accept_poly(server, &workers, on_accept) err = nbio.run() assert(err == nil) on_accept :: proc(op: ^nbio.Operation, workers: ^thread.Pool) { assert(op.accept.err == nil) nbio.accept_poly(op.accept.socket, workers, on_accept) thread.pool_add_task(workers, context.allocator, do_work, new_clone(Connection{ loop = op.l, socket = op.accept.client, })) } do_work :: proc(t: thread.Task) { connection := (^Connection)(t.data) // Imagine CPU intensive work that's been ofloaded to a worker thread. time.sleep(time.Second * 1) nbio.send_poly(connection.socket, {transmute([]byte)string("Hellope!\n")}, connection, on_sent, l=connection.loop) } on_sent :: proc(op: ^nbio.Operation, connection: ^Connection) { assert(op.send.err == nil) // Client got our message, clean up. nbio.close(connection.socket) free(connection) } } **Handle and socket association**: Most platforms require handles (files, sockets, etc.) to be explicitly associated with an event loop or configured for non-blocking/asynchronous operation. On some platforms (notably Windows), this requires a specific flag at open time (`.Non_Blocking` for `core:os`) and association may fail if the handle was not created correctly. For this reason, prefer `open` and `create_socket` from this package instead. `associate_handle`, `associate_file`, and `associate_socket` can be used for externally opened files/sockets. **Offsets and positional I/O**: Operations do not implicitly use or modify a handle’s internal file offset. Instead, operations such as `read` and `write` are *positional* and require an explicit offset. This avoids ambiguity and subtle bugs when multiple asynchronous operations are issued concurrently against the same handle. **Contexts and callbacks**: The `context` inside a callback is *not* the context that submitted the operation. Instead, the callback receives the context that was active when the event loop function (`tick`, `run`, etc.) was called. This is because otherwise the context would have to be copied and held onto for each operation. If the submitting context is required inside the callback, it must be copied into the operation’s user data explicitly. Example: nbio.timeout_poly(time.Second, new_clone(context), proc(_: ^Operation, ctx: ^runtime.Context) { context = ctx^ free(ctx) }) **Callback scheduling guarantees**: Callbacks are guaranteed to be invoked in a later tick, never synchronously. This means that the operation returned from a procedure is at least valid till the end of the current tick, because an operation is freed after it's callback is called. Thus you can set user data after an execution is queued, or call `remove`, removing subtle "race" conditions and simplifying control flow. **Why does the design of this package use callbacks?** Callbacks are the simplest interface an event loop can reasonably expose: "Run this when the operation completes". This means the loop itself doesn’t need to know how the result is consumed (You could give control of the entire loop to the user, but that comes with all the problems in that). Other mechanisms can be built on top of this, such as coroutines or even a queue you comsume at your own time. The choice of one `Operation` type and one callback type for all the operations is partly so it is easy to bind into Lua-like or native coroutines. Callbacks also allow multiple independent users to share the same event loop. A package can register its own operations, and application code can register others, without either seeing or handling the other’s completions.

Collection Info

View Source
Collection
core
Path
nbio
Entries
162

Source Files

(hidden platform specific files)

Constants

16

CWD #

Source
CWD :: _CWD

Sentinel handle representing the current/present working directory.

FULLY_SUPPORTED #

Source
FULLY_SUPPORTED :: _FULLY_SUPPORTED

If the package is fully supported on the current target. If it is not it will compile but work in a matter where things are unimplemented. Additionally if it is `FULLY_SUPPORTED` it may still return `.Unsupported` in `acquire_thread_event_loop` If the target does not support the needed syscalls for operating the package.

MAX_USER_ARGUMENTS #

Source
MAX_USER_ARGUMENTS :: #config(NBIO_MAX_USER_ARGUMENTS, 4)

The maximum size of user arguments for an operation, can be increased at the cost of more RAM.

Permissions_All #

Source
Permissions_All :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All

Read, write, and execute permissions for user, group, and others.

Permissions_Default_Directory #

Source
Permissions_Default_Directory :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All

Default permissions used when creating a directory (read, write, and execute for everyone).

Permissions_Default_File #

Source
Permissions_Default_File :: Permissions_Read_All + Permissions_Write_All

Default permissions used when creating a file (read and write for everyone).

Permissions_Execute_All #

Source
Permissions_Execute_All :: Permissions{.Execute_User, .Execute_Group, .Execute_Other}

Convenience permission sets.

Permissions_Read_All #

Source
Permissions_Read_All :: Permissions{.Read_User, .Read_Group, .Read_Other}

Permissions_Read_Write_All #

Source
Permissions_Read_Write_All :: Permissions_Read_All + Permissions_Write_All

Read and write permissions for user, group, and others.

Permissions_Write_All #

Source
Permissions_Write_All :: Permissions{.Write_User, .Write_Group, .Write_Other}

Config Values

1

MAX_USER_ARGUMENTS #

Source
MAX_USER_ARGUMENTS :: #config(NBIO_MAX_USER_ARGUMENTS, 4)

The maximum size of user arguments for an operation, can be increased at the cost of more RAM.

Types

54

Permissions #

Source
Permissions :: distinct Permissions

File permission bit-set. This type represents POSIX-style file permissions, split into user, group, and other categories, each with read, write, and execute flags.

Procedures

90

accept #

Source
accept :: proc(socket: TCP_Socket, cb: Callback, timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Using the given socket, accepts the next incoming connection, calling the callback when that happens. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `accept_poly`, `accept_poly2`, and `accept_poly3`. Inputs: - socket: A bound and listening socket *associated with the event loop* - cb: The callback to be called when the operation finishes, `Operation.accept` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

accept_poly #

Source
accept_poly :: proc(socket: TCP_Socket, p: $T, cb: $C/proc(op: ^Operation, p: $T), timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Using the given socket, accepts the next incoming connection, calling the callback when that happens. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: A bound and listening socket *associated with the event loop* - p: User data, the callback will receive this as it's second argument - cb: The callback to be called when the operation finishes, `Operation.accept` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

accept_poly2 #

Source
accept_poly2 :: proc(
	socket:  TCP_Socket, 
	p:       $T, 
	p2:      $T2, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2), 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Using the given socket, accepts the next incoming connection, calling the callback when that happens. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: A bound and listening socket *associated with the event loop* - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - cb: The callback to be called when the operation finishes, `Operation.accept` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

accept_poly3 #

Source
accept_poly3 :: proc(
	socket:  TCP_Socket, 
	p:       $T, 
	p2:      $T2, 
	p3:      $T3, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Using the given socket, accepts the next incoming connection, calling the callback when that happens. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: A bound and listening socket *associated with the event loop* - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - p3: User data, the callback will receive this as it's fourth argument - cb: The callback to be called when the operation finishes, `Operation.accept` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

acquire_thread_event_loop #

Source
acquire_thread_event_loop :: proc() -> General_Error {…}

Initialize or increment the reference counted event loop for the current thread.

associate_handle #

Source
associate_handle :: proc(handle: uintptr, l: ^Event_Loop = nil, loc := #caller_location) -> (_Handle, Association_Error) {…}

Associate the given OS handle, not opened through this package, with the event loop. Consider using this package's `open` or `open_sync` directly instead. The handle returned is for convenience, it is actually still the same handle as given. Thus you should not close the given handle. On Windows, this can error when a file is not opened with the `FILE_FLAG_OVERLAPPED` flag. If using `core:os`, that is set when you specify the `O_NONBLOCK` flag. There is no way to add that after the fact.

associate_socket #

Source
associate_socket :: proc(socket: Any_Socket, l: ^Event_Loop = nil, loc := #caller_location) -> Association_Error {…}

Associate the given socket, not created through this package, with the event loop. Consider using this package's `create_socket` directly instead.

close #

Source
close :: proc(subject: Closable, cb: Callback = empty_callback, l: ^Event_Loop = nil) -> ^Operation {…}

Closes the given subject (file or socket). Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. For consistent behavior first call `remove` on in progress IO. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `close_poly`, `close_poly2`, and `close_poly3`. Inputs: - subject: The subject (socket or file) to close - cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

close_poly #

Source
close_poly :: proc(subject: Closable, p: $T, cb: $C/proc(op: ^Operation, p: $T), l: ^Event_Loop = nil) -> ^Operation {…}

Closes the given subject (file or socket). Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. For consistent behavior first call `remove` on in progress IO. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - subject: The subject (socket or file) to close - p: User data, the callback will receive this as it's second argument - cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

close_poly2 #

Source
close_poly2 :: proc(subject: Closable, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), l: ^Event_Loop = nil) -> ^Operation {…}

Closes the given subject (file or socket). Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. For consistent behavior first call `remove` on in progress IO. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - subject: The subject (socket or file) to close - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

close_poly3 #

Source
close_poly3 :: proc(
	subject: Closable, 
	p:       $T, 
	p2:      $T2, 
	p3:      $T3, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Closes the given subject (file or socket). Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. For consistent behavior first call `remove` on in progress IO. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - subject: The subject (socket or file) to close - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - p3: User data, the callback will receive this as it's fourth argument - cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

create_socket #

Source
create_socket :: proc(family: Address_Family, protocol: Socket_Protocol, l: ^Event_Loop = nil, loc := #caller_location) -> (socket: Any_Socket, err: Create_Socket_Error) {…}

Creates a socket for use in `nbio` and relates it to the given event loop. Inputs: - family: Should this be an IP4 or IP6 socket - protocol: The type of socket (TCP or UDP) - l: The event loop to associate it with, defaults to the current thread's loop Returns: - socket: The created socket, consider `create_{udp|tcp}_socket` for a typed socket instead of the union - err: A network error (`Create_Socket_Error`, or `Set_Blocking_Error`) which happened while opening

create_tcp_socket #

Source
create_tcp_socket :: proc(family: Address_Family, l: ^Event_Loop = nil, loc := #caller_location) -> (TCP_Socket, Create_Socket_Error) {…}

Creates a TCP socket for use in `nbio` and relates it to the given event loop. Inputs: - family: Should this be an IP4 or IP6 socket - l: The event loop to associate it with, defaults to the current thread's loop Returns: - socket: The created TCP socket - err: A network error (`Create_Socket_Error`, or `Set_Blocking_Error`) which happened while opening

create_udp_socket #

Source
create_udp_socket :: proc(family: Address_Family, l: ^Event_Loop = nil, loc := #caller_location) -> (UDP_Socket, Create_Socket_Error) {…}

Creates a UDP socket for use in `nbio` and relates it to the given event loop. Inputs: - family: Should this be an IP4 or IP6 socket - l: The event loop to associate it with, defaults to the current thread's loop Returns: - socket: The created UDP socket - err: A network error (`Create_Socket_Error`, or `Set_Blocking_Error`) which happened while opening

detach #

Source
detach :: proc(op: ^Operation) {…}

Detach an operation from the package's lifetime management. By default the operation's lifetime is managed by the package and freed after a callback is called. Calling this function detaches the operation from this lifetime. You are expected to call `reattach` to give the package back this operation.

dial #

Source
dial :: proc(endpoint: Endpoint, cb: Callback, timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Dials the given endpoint. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `dial_poly`, `dial_poly2`, and `dial_poly3`. Inputs: - endpoint: The endpoint to connect to - cb: The callback to be called when the operation finishes, `Operation.dial` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

dial_poly #

Source
dial_poly :: proc(endpoint: Endpoint, p: $T, cb: $C/proc(op: ^Operation, p: $T), timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Dials the given endpoint. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - endpoint: The endpoint to connect to - p: User data, the callback will receive this as it's second argument - cb: The callback to be called when the operation finishes, `Operation.dial` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

dial_poly2 #

Source
dial_poly2 :: proc(
	endpoint: Endpoint, 
	p:        $T, 
	p2:       $T2, 
	cb:       $C/proc(op: ^Operation, p: $T, p2: $T2), 
	timeout:  Duration = NO_TIMEOUT, 
	l:        ^Event_Loop = nil, 
) -> ^Operation {…}

Dials the given endpoint. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - endpoint: The endpoint to connect to - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - cb: The callback to be called when the operation finishes, `Operation.dial` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

dial_poly3 #

Source
dial_poly3 :: proc(
	endpoint: Endpoint, 
	p:        $T, 
	p2:       $T2, 
	p3:       $T3, 
	cb:       $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	timeout:  Duration = NO_TIMEOUT, 
	l:        ^Event_Loop = nil, 
) -> ^Operation {…}

Dials the given endpoint. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - endpoint: The endpoint to connect to - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - p3: User data, the callback will receive this as it's fourth argument - cb: The callback to be called when the operation finishes, `Operation.dial` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

exec #

Source
exec :: proc(op: ^Operation, trigger_wake_up: bool = true) {…}

Execute an operation. If the operation is attached to another thread's event loop, it is queued to be executed on that event loop, optionally waking that loop up (from a blocking `tick`) with `trigger_wake_up`.

listen_tcp #

Source
listen_tcp :: proc(endpoint: Endpoint, backlog: int = 1000, l: ^Event_Loop = nil, loc := #caller_location) -> (socket: TCP_Socket, err: Network_Error) {…}

Creates a socket, sets non blocking mode, relates it to the given IO, binds the socket to the given endpoint and starts listening. Inputs: - endpoint: Where to bind the socket to - backlog: The maximum length to which the queue of pending connections may grow, before refusing connections - l: The event loop to associate the socket with, defaults to the current thread's loop Returns: - socket: The opened, bound and listening socket - err: A network error (`Create_Socket_Error`, `Bind_Error`, or `Listen_Error`) that has happened

next_tick_poly #

Source
next_tick_poly :: proc(p: $T, cb: $C/proc(op: ^Operation, p: $T), l: ^Event_Loop = nil) -> ^Operation {…}

Schedules an operation that completes on the next event loop tick. This is equivalent to `timeout_poly(0, ...)`.

next_tick_poly2 #

Source
next_tick_poly2 :: proc(p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), l: ^Event_Loop = nil) -> ^Operation {…}

Schedules an operation that completes on the next event loop tick. This is equivalent to `timeout_poly2(0, ...)`.

next_tick_poly3 #

Source
next_tick_poly3 :: proc(p: $T, p2: $T2, p3: $T3, cb: $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), l: ^Event_Loop = nil) -> ^Operation {…}

Schedules an operation that completes on the next event loop tick. This is equivalent to `timeout_poly3(0, ...)`.

now #

Source
now :: proc() -> Time {…}

Returns the current time (cached at most at the beginning of the current tick).

num_waiting #

Source
num_waiting :: proc(l: Maybe($T=^Event_Loop) = nil) -> int {…}

Returns the number of in-progress operations to be completed on the event loop.

open #

Source
open :: proc(
	path: string, 
	cb:   Callback, 
	mode: bit_set[File_Flag] = {.Read}, 
	perm: Permissions = Permissions_Default_File, 
	dir:  _Handle = CWD, 
	l:    ^Event_Loop = nil, 
) -> ^Operation {…}

Opens a file and associates it with the event loop. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `open_poly`, `open_poly2`, and `open_poly3`. Inputs: - path: Path to the file, if not absolute: relative from `dir` - cb: The callback to be called when the operation finishes, `Operation.open` will contain results - mode: File open mode flags, defaults to read-only - perm: Permissions to use when creating a file, defaults to read+write for everybody - dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

open_poly #

Source
open_poly :: proc(
	path: string, 
	p:    $T, 
	cb:   $C/proc(op: ^Operation, p: $T), 
	mode: bit_set[File_Flag] = {.Read}, 
	perm: Permissions = Permissions_Default_File, 
	dir:  _Handle = CWD, 
	l:    ^Event_Loop = nil, 
) -> ^Operation {…}

Opens a file and associates it with the event loop. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - path: Path to the file, if not absolute: relative from `dir` - p: User data, the callback will receive this as its second argument - cb: The callback to be called when the operation finishes, `Operation.open` will contain results - mode: File open mode flags, defaults to read-only - perm: Permissions to use when creating a file, defaults to read+write for everybody - dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

open_poly2 #

Source
open_poly2 :: proc(
	path: string, 
	p:    $T, 
	p2:   $T2, 
	cb:   $C/proc(op: ^Operation, p: $T, p2: $T2), 
	mode: bit_set[File_Flag] = {.Read}, 
	perm: Permissions = Permissions_Default_File, 
	dir:  _Handle = CWD, 
	l:    ^Event_Loop = nil, 
) -> ^Operation {…}

Opens a file and associates it with the event loop. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - path: Path to the file, if not absolute: relative from `dir` - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - cb: The callback to be called when the operation finishes, `Operation.open` will contain results - mode: File open mode flags, defaults to read-only - perm: Permissions to use when creating a file, defaults to read+write for everybody - dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

open_poly3 #

Source
open_poly3 :: proc(
	path: string, 
	p:    $T, 
	p2:   $T2, 
	p3:   $T3, 
	cb:   $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	mode: bit_set[File_Flag] = {.Read}, 
	perm: Permissions = Permissions_Default_File, 
	dir:  _Handle = CWD, 
	l:    ^Event_Loop = nil, 
) -> ^Operation {…}

Asynchronously opens a file and associates it with the event loop. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - path: Path to the file, if not absolute: relative from `dir` - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - p3: User data, the callback will receive this as its fourth argument - cb: The callback to be called when the operation finishes, `Operation.open` will contain results - mode: File open mode flags, defaults to read-only - perm: Permissions to use when creating a file, defaults to read+write for everybody - dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

open_sync #

Source
open_sync :: proc(
	path: string, 
	dir:  _Handle = CWD, 
	mode: bit_set[File_Flag] = {.Read}, 
	perm: Permissions = Permissions_Default_File, 
	l:    ^Event_Loop = nil, 
	loc := #caller_location, 
) -> (handle: _Handle, err: FS_Error) {…}

Opens a file and associates it with the event loop. Inputs: - path: path to the file, if not absolute: relative from `dir` - dir: directory that `path` is relative from (if it is relative), defaults to the current working directory - mode: open mode, defaults to read-only - perm: permissions to use when creating a file, defaults to read+write for everybody - l: event loop to associate the file with, defaults to the current thread's Returns: - handle: The file handle - err: An error if it occurred

poll #

Source
poll :: proc(socket: Any_Socket, event: Poll_Event, cb: Callback, timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Poll a socket for readiness. NOTE: this is provided to help with "legacy" APIs that require polling behavior. If you can avoid it and use the other procs in this package, do so. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `poll_poly`, `poll_poly2`, and `poll_poly3`. Inputs: - socket: Socket to poll that is *associated with the event loop* - event: Event to poll for - cb: The callback to be called when the operation finishes, `Operation.poll` will contain results - timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

poll_poly #

Source
poll_poly :: proc(
	socket:  Any_Socket, 
	event:   Poll_Event, 
	p:       $T, 
	cb:      $C/proc(op: ^Operation, p: $T), 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Poll a socket for readiness. NOTE: this is provided to help with "legacy" APIs that require polling behavior. If you can avoid it and use the other procs in this package, do so. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: Socket to poll that is *associated with the event loop* - event: Event to poll for - p: User data, the callback will receive this as its second argument - cb: The callback to be called when the operation finishes, `Operation.poll` will contain results - timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

poll_poly2 #

Source
poll_poly2 :: proc(
	socket:  Any_Socket, 
	event:   Poll_Event, 
	p:       $T, 
	p2:      $T2, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2), 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Poll a socket for readiness. NOTE: this is provided to help with "legacy" APIs that require polling behavior. If you can avoid it and use the other procs in this package, do so. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: Socket to poll that is *associated with the event loop* - event: Event to poll for - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - cb: The callback to be called when the operation finishes, `Operation.poll` will contain results - timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

poll_poly3 #

Source
poll_poly3 :: proc(
	socket:  Any_Socket, 
	event:   Poll_Event, 
	p:       $T, 
	p2:      $T2, 
	p3:      $T3, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Poll a socket for readiness. NOTE: this is provided to help with "legacy" APIs that require polling behavior. If you can avoid it and use the other procs in this package, do so. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: Socket to poll that is *associated with the event loop* - event: Event to poll for - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - p3: User data, the callback will receive this as its fourth argument - cb: The callback to be called when the operation finishes, `Operation.poll` will contain results - timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_accept #

Source
prep_accept :: proc(socket: TCP_Socket, cb: Callback, timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Retrieves and preps an operation to do an accept without executing it. Executing can then be done with the `exec` procedure. The timeout is calculated from the time when this procedure was called, not from when it's executed. Any user data can be set on the returned operation's `user_data` field. Inputs: - socket: A bound and listening socket *associated with the event loop* - cb: The callback to be called when the operation finishes, `Operation.accept` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_close #

Source
prep_close :: proc(subject: Closable, cb: Callback = empty_callback, l: ^Event_Loop = nil) -> ^Operation {…}

Retrieves and preps an operation to do a close without executing it. Executing can then be done with the `exec` procedure. Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. For consistent behavior first call `remove` on in progress IO. Any user data can be set on the returned operation's `user_data` field. Inputs: - subject: The subject (socket or file) to close - cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_dial #

Source
prep_dial :: proc(endpoint: Endpoint, cb: Callback, timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Retrieves and preps an operation to do a dial operation without executing it. Executing can then be done with the `exec` procedure. The timeout is calculated from the time when this procedure was called, not from when it's executed. Any user data can be set on the returned operation's `user_data` field. Inputs: - endpoint: The endpoint to connect to - cb: The callback to be called when the operation finishes, `Operation.dial` will contain results - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_next_tick #

Source
prep_next_tick :: proc(cb: Callback, l: ^Event_Loop = nil) -> ^Operation {…}

Retrieves and preps an operation that completes on the next event loop tick. This is equivalent to `prep_timeout(0, ...)`.

prep_open #

Source
prep_open :: proc(
	path: string, 
	cb:   Callback, 
	mode: bit_set[File_Flag] = {.Read}, 
	perm: Permissions = Permissions_Default_File, 
	dir:  _Handle = CWD, 
	l:    ^Event_Loop = nil, 
) -> ^Operation {…}

Retrieves and preps an operation to open a file without executing it. Executing can then be done with the `exec` procedure. Any user data can be set on the returned operation's `user_data` field. Inputs: - path: Path to the file, if not absolute: relative from `dir` - cb: The callback to be called when the operation finishes, `Operation.open` will contain results - mode: File open mode flags, defaults to read-only - perm: Permissions to use when creating a file, defaults to read+write for everybody - dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_poll #

Source
prep_poll :: proc(socket: Any_Socket, event: Poll_Event, cb: Callback, timeout: Duration = NO_TIMEOUT, l: ^Event_Loop = nil) -> ^Operation {…}

Retrieves and preps an operation to poll a socket without executing it. Executing can then be done with the `exec` procedure. The timeout is calculated from the time when this procedure was called, not from when it's executed. Any user data can be set on the returned operation's `user_data` field. Inputs: - socket: Socket to poll that is *associated with the event loop* - event: Event to poll for - cb: The callback to be called when the operation finishes, `Operation.poll` will contain results - timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_read #

Source
prep_read :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	cb:      Callback, 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Retrieves and preps a positional read operation without executing it. This is a pread-style operation: the read starts at the given offset and does not modify the handle's current file position. Executing can then be done with the `exec` procedure. The timeout is calculated from the time when this procedure was called, not from when it's executed. Any user data can be set on the returned operation's `user_data` field. Inputs: - handle: Handle to read from - offset: Offset to read from - buf: Buffer to read data into (must not be empty) - cb: The callback to be called when the operation finishes, `Operation.read` will contain results - all: Whether to read until the buffer is full or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_recv #

Source
prep_recv :: proc(
	socket:  Any_Socket, 
	bufs:    [][]u8, 
	cb:      Callback, 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Retrieves and preps an operation to do a receive without executing it. Executing can then be done with the `exec` procedure. To avoid ambiguity between a closed connection and a 0-byte read, the provided buffers must have a total capacity greater than 0. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. The timeout is calculated from the time when this procedure was called, not from when it's executed. Any user data can be set on the returned operation's `user_data` field. Inputs: - socket: The socket to receive from - bufs: Buffers to fill with received data - cb: The callback to be called when the operation finishes, `Operation.recv` will contain results - all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_send #

Source
prep_send :: proc(
	socket:   Any_Socket, 
	bufs:     [][]u8, 
	cb:       Callback, 
	endpoint: Endpoint = {}, 
	all:      bool = true, 
	timeout:  Duration = NO_TIMEOUT, 
	l:        ^Event_Loop = nil, 
) -> ^Operation {…}

Retrieves and preps an operation to do a send without executing it. Executing can then be done with the `exec` procedure. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. The timeout is calculated from the time when this procedure was called, not from when it's executed. Any user data can be set on the returned operation's `user_data` field. Inputs: - socket: The socket to send to - bufs: Buffers containing the data to send - cb: The callback to be called when the operation finishes, `Operation.send` will contain results - endpoint: The destination endpoint (UDP only, ignored for TCP) - all: If true, the operation ensures all data is sent before completing - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_sendfile #

Source
prep_sendfile :: proc(
	socket:           TCP_Socket, 
	file:             _Handle, 
	cb:               Callback, 
	offset:           int = 0, 
	nbytes:           int = SEND_ENTIRE_FILE, 
	progress_updates: bool = false, 
	timeout:          Duration = NO_TIMEOUT, 
	l:                ^Event_Loop = nil, 
) -> ^Operation {…}

Retrieves and preps an operation to send a file over a socket without executing it. Executing can then be done with the `exec` procedure. This uses high-performance zero-copy system calls where available. Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. Any user data can be set on the returned operation's `user_data` field. Inputs: - socket: The destination TCP socket - file: The source file handle - cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes - offset: Byte offset to start reading from the file - nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) - progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the final callback is called

prep_stat #

Source
prep_stat :: proc(handle: _Handle, cb: Callback, l: ^Event_Loop = nil) -> ^Operation {…}

Retrieves and preps an operation to stat a handle without executing it. Executing can then be done with the `exec` procedure. Any user data can be set on the returned operation's `user_data` field. Inputs: - handle: Handle to retrieve stat - cb: The callback to be called when the operation finishes, `Operation.stat` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_timeout #

Source
prep_timeout :: proc(duration: Duration, cb: Callback, l: ^Event_Loop = nil) -> ^Operation {…}

Retrieves and preps a timeout operation without executing it. Executing can then be done with the `exec` procedure. Any user data can be set on the returned operation's `user_data` field. Inputs: - duration: Duration to wait before the operation completes - cb: The callback to be called when the operation finishes - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

prep_write #

Source
prep_write :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	cb:      Callback, 
	all:     bool = true, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Retrieves and preps a positional write operation without executing it. This is a pwrite-style operation: the write starts at the given offset and does not modify the handle's current file position. Executing can then be done with the `exec` procedure. The timeout is calculated from the time when this procedure was called, not from when it's executed. Any user data can be set on the returned operation's `user_data` field. Inputs: - handle: Handle to write to - offset: Offset to write to - buf: Buffer containing data to write (must not be empty) - cb: The callback to be called when the operation finishes, `Operation.write` will contain results - all: Whether to write until the entire buffer is written or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

read #

Source
read :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	cb:      Callback, 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Reads data from a handle at a specific offset. This is a pread-style operation: the read starts at the given offset and does not modify the handle's current file position. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `read_poly`, `read_poly2`, and `read_poly3`. Inputs: - handle: Handle to read from - offset: Offset to read from - buf: Buffer to read data into (must not be empty) - cb: The callback to be called when the operation finishes, `Operation.read` will contain results - all: Whether to read until the buffer is full or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

read_entire_file #

Source
read_entire_file :: proc(
	path:      string, 
	user_data: rawptr, 
	cb:        Read_Entire_File_Callback, 
	allocator := context.allocator, 
	dir:       _Handle = CWD, 
	l:         ^Event_Loop = nil, 
	loc := #caller_location, 
) {…}

Combines multiple operations (open, stat, read, close) into one that reads an entire regular file. The error contains the `operation` that the error happened on. Inputs: - path: path to the file, if not absolute: relative from `dir` - user_data: a pointer passed through into the callback - cb: the callback to call once completed, called with the user data, file data, and an optional error - allocator: the allocator to allocate the file's contents onto - dir: directory that `path` is relative from (if it is relative), defaults to the current working directory - l: event loop to execute the operation on

read_poly #

Source
read_poly :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	p:       $T, 
	cb:      $C/proc(op: ^Operation, p: $T), 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Reads data from a handle at a specific offset. This is a pread-style operation: the read starts at the given offset and does not modify the handle's current file position. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to read from - offset: Offset to read from - buf: Buffer to read data into (must not be empty) - p: User data, the callback will receive this as its second argument - cb: The callback to be called when the operation finishes, `Operation.read` will contain results - all: Whether to read until the buffer is full or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

read_poly2 #

Source
read_poly2 :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	p:       $T, 
	p2:      $T2, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2), 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Reads data from a handle at a specific offset. This is a pread-style operation: the read starts at the given offset and does not modify the handle's current file position. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to read from - offset: Offset to read from - buf: Buffer to read data into (must not be empty) - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - cb: The callback to be called when the operation finishes, `Operation.read` will contain results - all: Whether to read until the buffer is full or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

read_poly3 #

Source
read_poly3 :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	p:       $T, 
	p2:      $T2, 
	p3:      $T3, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Reads data from a handle at a specific offset. This is a pread-style operation: the read starts at the given offset and does not modify the handle's current file position. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to read from - offset: Offset to read from - buf: Buffer to read data into (must not be empty) - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - p3: User data, the callback will receive this as its fourth argument - cb: The callback to be called when the operation finishes, `Operation.read` will contain results - all: Whether to read until the buffer is full or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

reattach #

Source
reattach :: proc(op: ^Operation) {…}

Reattach an operation to the package's lifetime management.

recv #

Source
recv :: proc(
	socket:  Any_Socket, 
	bufs:    [][]u8, 
	cb:      Callback, 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Receives data from the socket. If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `recv_poly`, `recv_poly2`, and `recv_poly3`. Inputs: - socket: The socket to receive from - bufs: Buffers to fill with received data - cb: The callback to be called when the operation finishes, `Operation.recv` will contain results - all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

recv_poly #

Source
recv_poly :: proc(
	socket:  Any_Socket, 
	bufs:    [][]u8, 
	p:       $T, 
	cb:      $C/proc(op: ^Operation, p: $T), 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Receives data from the socket. If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The socket to receive from - bufs: Buffers to fill with received data - p: User data, the callback will receive this as it's second argument - cb: The callback to be called when the operation finishes, `Operation.recv` will contain results - all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

recv_poly2 #

Source
recv_poly2 :: proc(
	socket:  Any_Socket, 
	bufs:    [][]u8, 
	p:       $T, 
	p2:      $T2, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2), 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Receives data from the socket. If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The socket to receive from - bufs: Buffers to fill with received data - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - cb: The callback to be called when the operation finishes, `Operation.recv` will contain results - all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

recv_poly3 #

Source
recv_poly3 :: proc(
	socket:  Any_Socket, 
	bufs:    [][]u8, 
	p:       $T, 
	p2:      $T2, 
	p3:      $T3, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	all:     bool = false, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Receives data from the socket. If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The socket to receive from - bufs: Buffers to fill with received data - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - p3: User data, the callback will receive this as it's fourth argument - cb: The callback to be called when the operation finishes, `Operation.recv` will contain results - all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

release_thread_event_loop #

Source
release_thread_event_loop :: proc() {…}

Destroy or decrease the reference counted event loop for the current thread.

remove #

Source
remove :: proc(target: ^Operation) {…}

Remove the given operation from the event loop. The callback of it won't be called and resources are freed. Calling `remove`: - Cancels the operation if it has not yet completed - Prevents the callback from being called Cancellation via `remove` is *final* and silent: - The callback will never be invoked - No error is delivered - The operation must be considered dead after removal WARN: the operation could have already been (partially or completely) completed. A send with `all` set to true could have sent a portion already. But also, a send that could be completed without blocking could have been completed. You just won't get a callback. WARN: once an operation's callback is called it can not be removed anymore (use after free). WARN: needs to be called from the thread of the event loop the target belongs to. Common use would be to cancel a timeout, remove a polling, or remove an `accept` before calling `close` on it's socket.

run_until #

Source
run_until :: proc(done: ^bool) -> General_Error {…}

Runs the event loop by ticking in a loop until there is no more work to be done, or the flag `done` is `true`.

send #

Source
send :: proc(
	socket:   Any_Socket, 
	bufs:     [][]u8, 
	cb:       Callback, 
	endpoint: Endpoint = {}, 
	all:      bool = true, 
	timeout:  Duration = NO_TIMEOUT, 
	l:        ^Event_Loop = nil, 
) -> ^Operation {…}

Sends data to the socket. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `send_poly`, `send_poly2`, and `send_poly3`. Inputs: - socket: The socket to send to - bufs: Buffers containing the data to send - cb: The callback to be called when the operation finishes, `Operation.send` will contain results - endpoint: The destination endpoint (UDP only, ignored for TCP) - all: If true, the operation ensures all data is sent before completing - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

send_poly #

Source
send_poly :: proc(
	socket:   Any_Socket, 
	bufs:     [][]u8, 
	p:        $T, 
	cb:       $C/proc(op: ^Operation, p: $T), 
	endpoint: Endpoint = {}, 
	all:      bool = true, 
	timeout:  Duration = NO_TIMEOUT, 
	l:        ^Event_Loop = nil, 
) -> ^Operation {…}

Sends data to the socket. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The socket to send to - bufs: Buffers containing the data to send - p: User data, the callback will receive this as it's second argument - cb: The callback to be called when the operation finishes, `Operation.send` will contain results - endpoint: The destination endpoint (UDP only, ignored for TCP) - all: If true, the operation ensures all data is sent before completing - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

send_poly2 #

Source
send_poly2 :: proc(
	socket:   Any_Socket, 
	bufs:     [][]u8, 
	p:        $T, 
	p2:       $T2, 
	cb:       $C/proc(op: ^Operation, p: $T, p2: $T2), 
	endpoint: Endpoint = {}, 
	all:      bool = true, 
	timeout:  Duration = NO_TIMEOUT, 
	l:        ^Event_Loop = nil, 
) -> ^Operation {…}

Sends data to the socket. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The socket to send to - bufs: Buffers containing the data to send - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - cb: The callback to be called when the operation finishes, `Operation.send` will contain results - endpoint: The destination endpoint (UDP only, ignored for TCP) - all: If true, the operation ensures all data is sent before completing - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

send_poly3 #

Source
send_poly3 :: proc(
	socket:   Any_Socket, 
	bufs:     [][]u8, 
	p:        $T, 
	p2:       $T2, 
	p3:       $T3, 
	cb:       $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	endpoint: Endpoint = {}, 
	all:      bool = true, 
	timeout:  Duration = NO_TIMEOUT, 
	l:        ^Event_Loop = nil, 
) -> ^Operation {…}

Sends data to the socket. The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The socket to send to - bufs: Buffers containing the data to send - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - p3: User data, the callback will receive this as it's fourth argument - cb: The callback to be called when the operation finishes, `Operation.send` will contain results - endpoint: The destination endpoint (UDP only, ignored for TCP) - all: If true, the operation ensures all data is sent before completing - timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

sendfile #

Source
sendfile :: proc(
	socket:           TCP_Socket, 
	file:             _Handle, 
	cb:               Callback, 
	offset:           int = 0, 
	nbytes:           int = SEND_ENTIRE_FILE, 
	progress_updates: bool = false, 
	timeout:          Duration = NO_TIMEOUT, 
	l:                ^Event_Loop = nil, 
) -> ^Operation {…}

Sends a file over a TCP socket. This uses high-performance zero-copy system calls where available. Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `sendfile_poly`, `sendfile_poly2`, and `sendfile_poly3`. Inputs: - socket: The destination TCP socket - file: The source file handle - cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes - offset: Byte offset to start reading from the file - nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) - progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the final callback is called

sendfile_poly #

Source
sendfile_poly :: proc(
	socket:           TCP_Socket, 
	file:             _Handle, 
	p:                $T, 
	cb:               $C/proc(op: ^Operation, p: $T), 
	offset:           int = 0, 
	nbytes:           int = SEND_ENTIRE_FILE, 
	progress_updates: bool = false, 
	timeout:          Duration = NO_TIMEOUT, 
	l:                ^Event_Loop = nil, 
) -> ^Operation {…}

Sends a file over a TCP socket. This uses high-performance zero-copy system calls where available. Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The destination TCP socket - file: The source file handle - p: User data, the callback will receive this as it's second argument - cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes - offset: Byte offset to start reading from the file - nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) - progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the final callback is called

sendfile_poly2 #

Source
sendfile_poly2 :: proc(
	socket:           TCP_Socket, 
	file:             _Handle, 
	p:                $T, 
	p2:               $T2, 
	cb:               $C/proc(op: ^Operation, p: $T, p2: $T2), 
	offset:           int = 0, 
	nbytes:           int = SEND_ENTIRE_FILE, 
	progress_updates: bool = false, 
	timeout:          Duration = NO_TIMEOUT, 
	l:                ^Event_Loop = nil, 
) -> ^Operation {…}

Sends a file over a TCP socket. This uses high-performance zero-copy system calls where available. Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The destination TCP socket - file: The source file handle - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes - offset: Byte offset to start reading from the file - nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) - progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the final callback is called

sendfile_poly3 #

Source
sendfile_poly3 :: proc(
	socket:           TCP_Socket, 
	file:             _Handle, 
	p:                $T, 
	p2:               $T2, 
	p3:               $T3, 
	cb:               $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	offset:           int = 0, 
	nbytes:           int = SEND_ENTIRE_FILE, 
	progress_updates: bool = false, 
	timeout:          Duration = NO_TIMEOUT, 
	l:                ^Event_Loop = nil, 
) -> ^Operation {…}

Sends a file over a TCP socket. This uses high-performance zero-copy system calls where available. Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - socket: The destination TCP socket - file: The source file handle - p: User data, the callback will receive this as it's second argument - p2: User data, the callback will receive this as it's third argument - p3: User data, the callback will receive this as it's fourth argument - cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes - offset: Byte offset to start reading from the file - nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) - progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the final callback is called

stat #

Source
stat :: proc(handle: _Handle, cb: Callback, l: ^Event_Loop = nil) -> ^Operation {…}

Stats a handle. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `stat_poly`, `stat_poly2`, and `stat_poly3`. Inputs: - handle: Handle to retrieve status information for - cb: The callback to be called when the operation finishes, `Operation.stat` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

stat_poly #

Source
stat_poly :: proc(handle: _Handle, p: $T, cb: $C/proc(op: ^Operation, p: $T), l: ^Event_Loop = nil) -> ^Operation {…}

Stats a handle. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to retrieve status information for - p: User data, the callback will receive this as its second argument - cb: The callback to be called when the operation finishes, `Operation.stat` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

stat_poly2 #

Source
stat_poly2 :: proc(handle: _Handle, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), l: ^Event_Loop = nil) -> ^Operation {…}

Stats a handle. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to retrieve status information for - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - cb: The callback to be called when the operation finishes, `Operation.stat` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

stat_poly3 #

Source
stat_poly3 :: proc(
	handle: _Handle, 
	p:      $T, 
	p2:     $T2, 
	p3:     $T3, 
	cb:     $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	l:      ^Event_Loop = nil, 
) -> ^Operation {…}

Stats a handle. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to retrieve status information for - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - p3: User data, the callback will receive this as its fourth argument - cb: The callback to be called when the operation finishes, `Operation.stat` will contain results - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

tick #

Source
tick :: proc(timeout: Duration = NO_TIMEOUT) -> General_Error {…}

Each time you call this the implementation checks its state and calls any callbacks which are ready. You would typically call this in a loop. Blocks for up-to timeout waiting for events if there is nothing to do.

timeout #

Source
timeout :: proc(duration: Duration, cb: Callback, l: ^Event_Loop = nil) -> ^Operation {…}

Schedules a timeout that completes after the given duration. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `timeout_poly`, `timeout_poly2`, and `timeout_poly3`. Inputs: - duration: Duration to wait before the operation completes - cb: The callback to be called when the operation finishes - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

timeout_poly #

Source
timeout_poly :: proc(dur: Duration, p: $T, cb: $C/proc(op: ^Operation, p: $T), l: ^Event_Loop = nil) -> ^Operation {…}

Schedules a timeout that completes after the given duration. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - dur: Duration to wait before the operation completes - p: User data, the callback will receive this as its second argument - cb: The callback to be called when the operation finishes - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

timeout_poly2 #

Source
timeout_poly2 :: proc(dur: Duration, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), l: ^Event_Loop = nil) -> ^Operation {…}

Schedules a timeout that completes after the given duration. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - dur: Duration to wait before the operation completes - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - cb: The callback to be called when the operation finishes - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

timeout_poly3 #

Source
timeout_poly3 :: proc(
	dur: Duration, 
	p:   $T, 
	p2:  $T2, 
	p3:  $T3, 
	cb:  $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	l:   ^Event_Loop = nil, 
) -> ^Operation {…}

Schedules a timeout that completes after the given duration. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - dur: Duration to wait before the operation completes - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - p3: User data, the callback will receive this as its fourth argument - cb: The callback to be called when the operation finishes - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

wake_up #

Source
wake_up :: proc(l: ^Event_Loop) {…}

Wake up an event loop on another thread which may be blocking for completed operations. Commonly used with `exec` from a worker thread to have the event loop pick up that work. Note that by default `exec` already calls this procedure.

write #

Source
write :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	cb:      Callback, 
	all:     bool = true, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Writes data to a handle at a specific offset. This is a pwrite-style operation: the write starts at the given offset and does not modify the handle's current file position. Any user data can be set on the returned operation's `user_data` field. Polymorphic variants for type safe user data are available under `write_poly`, `write_poly2`, and `write_poly3`. Inputs: - handle: Handle to write to - offset: Offset to write to - buf: Buffer containing data to write (must not be empty) - cb: The callback to be called when the operation finishes, `Operation.write` will contain results - all: Whether to write until the entire buffer is written or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

write_poly #

Source
write_poly :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	p:       $T, 
	cb:      $C/proc(op: ^Operation, p: $T), 
	all:     bool = true, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Writes data to a handle at a specific offset. This is a pwrite-style operation: the write starts at the given offset and does not modify the handle's current file position. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to write to - offset: Offset to write to - buf: Buffer containing data to write (must not be empty) - p: User data, the callback will receive this as its second argument - cb: The callback to be called when the operation finishes, `Operation.write` will contain results - all: Whether to write until the entire buffer is written or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

write_poly2 #

Source
write_poly2 :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	p:       $T, 
	p2:      $T2, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2), 
	all:     bool = true, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Writes data to a handle at a specific offset. This is a pwrite-style operation: the write starts at the given offset and does not modify the handle's current file position. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to write to - offset: Offset to write to - buf: Buffer containing data to write (must not be empty) - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - cb: The callback to be called when the operation finishes, `Operation.write` will contain results - all: Whether to write until the entire buffer is written or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

write_poly3 #

Source
write_poly3 :: proc(
	handle:  _Handle, 
	offset:  int, 
	buf:     []u8, 
	p:       $T, 
	p2:      $T2, 
	p3:      $T3, 
	cb:      $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), 
	all:     bool = true, 
	timeout: Duration = NO_TIMEOUT, 
	l:       ^Event_Loop = nil, 
) -> ^Operation {…}

Writes data to a handle at a specific offset. This is a pwrite-style operation: the write starts at the given offset and does not modify the handle's current file position. This procedure uses polymorphism for type safe user data up to a certain size. Inputs: - handle: Handle to write to - offset: Offset to write to - buf: Buffer containing data to write (must not be empty) - p: User data, the callback will receive this as its second argument - p2: User data, the callback will receive this as its third argument - p3: User data, the callback will receive this as its fourth argument - cb: The callback to be called when the operation finishes, `Operation.write` will contain results - all: Whether to write until the entire buffer is written or an error occurs - timeout: Optional timeout for the operation - l: Event loop to associate the operation with, defaults to the current thread's loop Returns: A non-nil pointer to the operation, alive until the callback is called

Procedure Groups

1