package core:nbio
Overview
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.
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.
Index
Types (54)
- Accept
- Accept_Error
- Address
- Address_Family
- Any_Socket
- Association_Error
- Callback
- Closable
- Close
- Create_Socket_Error
- Dial
- Dial_Error
- Endpoint
- Error
- Event_Loop
- FS_Error
- File_Flag
- File_Flags
- File_Type
- General_Error
- Handle
- IP4_Address
- IP6_Address
- Listen_Error
- Network_Error
- Open
- Operation
- Operation_Type
- Permission_Flag
- Permissions
- Platform_Error
- Poll
- Poll_Event
- Poll_Result
- Read
- Read_Entire_File_Callback
- Read_Entire_File_Error
- Recv
- Recv_Error
- Send
- Send_Error
- Send_File
- Send_File_Error
- Socket_Protocol
- Specifics
- Stat
- TCP_Recv_Error
- TCP_Send_Error
- TCP_Socket
- Timeout
- UDP_Recv_Error
- UDP_Send_Error
- UDP_Socket
- Write
Variables (0)
This section is empty.
Procedures (90)
- accept
- accept_poly
- accept_poly2
- accept_poly3
- acquire_thread_event_loop
- associate_handle
- associate_socket
- close
- close_poly
- close_poly2
- close_poly3
- create_socket
- create_tcp_socket
- create_udp_socket
- current_thread_event_loop
- detach
- dial
- dial_poly
- dial_poly2
- dial_poly3
- error_string
- error_string_recv
- error_string_send
- error_string_sendfile
- exec
- listen_tcp
- next_tick
- next_tick_poly
- next_tick_poly2
- next_tick_poly3
- now
- num_waiting
- open
- open_poly
- open_poly2
- open_poly3
- open_sync
- poll
- poll_poly
- poll_poly2
- poll_poly3
- prep_accept
- prep_close
- prep_dial
- prep_next_tick
- prep_open
- prep_poll
- prep_read
- prep_recv
- prep_send
- prep_sendfile
- prep_stat
- prep_timeout
- prep_write
- read
- read_entire_file
- read_poly
- read_poly2
- read_poly3
- reattach
- recv
- recv_poly
- recv_poly2
- recv_poly3
- release_thread_event_loop
- remove
- run
- run_until
- send
- send_poly
- send_poly2
- send_poly3
- sendfile
- sendfile_poly
- sendfile_poly2
- sendfile_poly3
- stat
- stat_poly
- stat_poly2
- stat_poly3
- tick
- timeout
- timeout_poly
- timeout_poly2
- timeout_poly3
- wake_up
- write
- write_poly
- write_poly2
- write_poly3
Procedure Groups (0)
This section is empty.
Types
Accept ¶
Accept :: struct { // Socket to accept an incoming connection on. socket: net.TCP_Socket, // When this operation expires and should be timed out. expires: time.Time, // The connection that was accepted. client: net.TCP_Socket, // The connection's remote origin. client_endpoint: net.Endpoint, // An error, if it occurred. err: net.Accept_Error, // Implementation specifics, private. _impl: _Accept `fmt:"-"`, }
Accept_Error ¶
Accept_Error :: net.Accept_Error
Any_Socket ¶
Any_Socket :: net.Any_Socket
Related Procedures With Parameters
Related Procedures With Returns
Association_Error ¶
Association_Error :: enum int { None, // The given file/handle/socket was not opened in a mode that it can be made non-blocking afterwards. // // On Windows, this can happen 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. Not_Possible_To_Associate, // The given handle is not a valid handle. Invalid_Handle, // No network connection, or the network stack is not initialized. Network_Unreachable, }
Related Procedures With Returns
Closable ¶
Closable :: union { net.TCP_Socket, net.UDP_Socket, _Handle, }
A union of closable types that can be passed to close.
Related Procedures With Parameters
Create_Socket_Error ¶
Create_Socket_Error :: net.Create_Socket_Error
Related Procedures With Returns
Dial ¶
Dial :: struct { // The endpoint to connect to. endpoint: net.Endpoint, // When this operation expires and should be timed out. expires: time.Time, // Errors that can be returned: `Create_Socket_Error`, or `Dial_Error`. err: net.Network_Error, // The socket to communicate with the connected server. socket: net.TCP_Socket, // Implementation specifics, private. _impl: _Dial `fmt:"-"`, }
Dial_Error ¶
Dial_Error :: net.Dial_Error
Error ¶
Error :: union { net.Create_Socket_Error, net.Dial_Error, net.Listen_Error, net.Accept_Error, net.Bind_Error, net.TCP_Send_Error, net.UDP_Send_Error, net.TCP_Recv_Error, net.UDP_Recv_Error, net.Shutdown_Error, net.Interfaces_Error, net.Socket_Info_Error, net.Socket_Option_Error, net.Set_Blocking_Error, net.Parse_Endpoint_Error, net.Resolve_Error, net.DNS_Error, General_Error, FS_Error, }
Related Procedures With Parameters
Event_Loop ¶
Event_Loop :: struct { using impl: _Event_Loop, err: General_Error, refs: int, now: time.Time, // Queue that is used to queue operations from another thread to be executed on this thread. // TODO: Better data-structure. queue: container_queue.Queue($T=^Operation), queue_mu: sync.Mutex, operation_pool: container_pool.Pool($T=Operation), }
An event loop, one per thread, consider the fields private. Do not copy.
Related Procedures With Parameters
- accept
- accept_poly
- accept_poly2
- accept_poly3
- associate_handle
- associate_socket
- close
- close_poly
- close_poly2
- close_poly3
- create_socket
- create_tcp_socket
- create_udp_socket
- dial
- dial_poly
- dial_poly2
- dial_poly3
- listen_tcp
- next_tick
- next_tick_poly
- next_tick_poly2
- next_tick_poly3
- open
- open_poly
- open_poly2
- open_poly3
- open_sync
- poll
- poll_poly
- poll_poly2
- poll_poly3
- prep_accept
- prep_close
- prep_dial
- prep_next_tick
- prep_open
- prep_poll
- prep_read
- prep_recv
- prep_send
- prep_sendfile
- prep_stat
- prep_timeout
- prep_write
- read
- read_entire_file
- read_poly
- read_poly2
- read_poly3
- recv
- recv_poly
- recv_poly2
- recv_poly3
- send
- send_poly
- send_poly2
- send_poly3
- sendfile
- sendfile_poly
- sendfile_poly2
- sendfile_poly3
- stat
- stat_poly
- stat_poly2
- stat_poly3
- timeout
- timeout_poly
- timeout_poly2
- timeout_poly3
- wake_up
- write
- write_poly
- write_poly2
- write_poly3
Related Procedures With Returns
FS_Error ¶
FS_Error :: enum i32 { None, Unsupported = 50, Allocation_Failed = 14, Timeout = 258, Invalid_Argument = 160, Permission_Denied = 5, EOF = 38, Exists = 80, Not_Found = 2, }
Errors gotten from file system operations.
Related Procedures With Returns
File_Flag ¶
File_Flag :: enum int { // Open for reading. Read, // Open for writing. Write, // Append writes to the end of the file. Append, // Create the file if it does not exist. Create, // Fail if the file already exists (used with Create). Excl, Sync, // Truncate the file on open. Trunc, }
File_Flags ¶
Related Procedures With Parameters
File_Type ¶
File_Type :: enum int { // File type could not be determined. Undetermined, // Regular file. Regular, // Directory. Directory, // Symbolic link. Symlink, // Pipe or socket. Pipe_Or_Socket, // Character or block device. Device, }
General_Error ¶
General_Error :: enum i32 { None, Allocation_Failed = 14, Unsupported = 50, }
Errors regarding general usage of the event loop.
Related Procedures With Returns
Handle ¶
Handle :: _Handle
Related Procedures With Parameters
Related Procedures With Returns
Related Constants
Listen_Error ¶
Listen_Error :: net.Listen_Error
Open ¶
Open :: struct { // Base directory the path is relative to. dir: _Handle, // Path to the file. path: string, // File open mode flags. mode: bit_set[File_Flag; int], // Permissions used if the file is created. perm: Permissions, // The opened file handle. handle: _Handle, // An error, if it occurred. err: FS_Error, // Implementation specifics, private. _impl: _Open `fmt:"-"`, }
Operation ¶
Operation :: struct { cb: Callback, user_data: [5]rawptr, detached: bool, type: Operation_Type, using specifics: Specifics, _impl: _Operation `fmt:"-"`, using _: struct #raw_union { _pool_link: ^Operation, l: ^Event_Loop, }, }
Related Procedures With Returns
- accept
- accept_poly
- accept_poly2
- accept_poly3
- close
- close_poly
- close_poly2
- close_poly3
- dial
- dial_poly
- dial_poly2
- dial_poly3
- next_tick
- next_tick_poly
- next_tick_poly2
- next_tick_poly3
- open
- open_poly
- open_poly2
- open_poly3
- poll
- poll_poly
- poll_poly2
- poll_poly3
- prep_accept
- prep_close
- prep_dial
- prep_next_tick
- prep_open
- prep_poll
- prep_read
- prep_recv
- prep_send
- prep_sendfile
- prep_stat
- prep_timeout
- prep_write
- read
- read_poly
- read_poly2
- read_poly3
- recv
- recv_poly
- recv_poly2
- recv_poly3
- send
- send_poly
- send_poly2
- send_poly3
- sendfile
- sendfile_poly
- sendfile_poly2
- sendfile_poly3
- stat
- stat_poly
- stat_poly2
- stat_poly3
- timeout
- timeout_poly
- timeout_poly2
- timeout_poly3
- write
- write_poly
- write_poly2
- write_poly3
Operation_Type ¶
Operation_Type :: enum i32 { None, Accept, Close, Dial, Read, Recv, Send, Write, Timeout, Poll, Send_File, Open, Stat, _Link_Timeout, _Remove, _Splice, }
Permission_Flag ¶
Permission_Flag :: enum u32 { Execute_Other = 0, Write_Other = 1, Read_Other = 2, Execute_Group = 3, Write_Group = 4, Read_Group = 5, Execute_User = 6, Write_User = 7, Read_User = 8, }
Permissions ¶
Permissions :: distinct bit_set[Permission_Flag; u32]
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.
Related Procedures With Parameters
Related Constants
Platform_Error ¶
Platform_Error :: sys_windows.System_Error
Poll ¶
Poll :: struct { // Socket to poll. socket: net.Any_Socket, // Event to poll for. event: Poll_Event, // When this operation expires and should be timed out. expires: time.Time, // Result of the poll. result: Poll_Result, // Implementation specifics, private. _impl: _Poll `fmt:"-"`, }
Poll_Event ¶
Poll_Event :: enum int { // The subject is ready to be received from. Receive, // The subject is ready to be sent to. Send, }
Related Procedures With Parameters
Poll_Result ¶
Poll_Result :: enum i32 { // The requested event is ready. Ready, // The operation timed out before the event became ready. Timeout, // The socket was invalid. Invalid_Argument, // An unspecified error occurred. Error, }
Read ¶
Read :: struct { // Handle to read from. handle: _Handle, // Buffer to read data into. buf: []u8 `fmt:"v,read"`, // Offset to read from. offset: int, // Whether to read until the buffer is full or an error occurs. all: bool, // When this operation expires and should be timed out. expires: time.Time, // Error, if it occurred. err: FS_Error, // Number of bytes read. read: int, // Implementation specifics, private. _impl: _Read `fmt:"-"`, }
Read_Entire_File_Callback ¶
Read_Entire_File_Callback :: proc(user_data: rawptr, data: []u8, err: Read_Entire_File_Error)
Related Procedures With Parameters
Read_Entire_File_Error ¶
Read_Entire_File_Error :: struct { operation: Operation_Type, value: FS_Error, }
Recv ¶
Recv :: struct { // The socket to receive from. socket: net.Any_Socket, // The buffers to receive data into. // The outer slice is copied internally, but the backing arrays must remain alive. // It is safe to access `bufs` during the callback. bufs: [][]u8, // If true, the operation waits until all buffers are filled (TCP only). all: bool, // When this operation expires and should be timed out. expires: time.Time, // The source endpoint data was received from (UDP only). source: net.Endpoint, // An error, if it occurred. // If `received == 0` and `err == nil`, the connection was closed by the peer. err: net.Recv_Error, // The number of bytes received. received: int, // Implementation specifics, private. _impl: _Recv `fmt:"-"`, }
Send ¶
Send :: struct { // The socket to send to. socket: net.Any_Socket, // The buffers to send. // The outer slice is copied internally, but the backing arrays must remain alive. bufs: [][]u8 `fmt:"-"`, // The destination endpoint to send to (UDP only). endpoint: net.Endpoint, // If true, the operation ensures all data is sent before completing. all: bool, // When this operation expires and should be timed out. expires: time.Time, // An error, if it occurred. err: net.Send_Error, // The number of bytes sent. sent: int, // Implementation specifics, private. _impl: _Send `fmt:"-"`, }
Send_File ¶
Send_File :: struct { // The TCP socket to send the file over. socket: net.TCP_Socket, // The handle of the regular file to send. file: _Handle, // When this operation expires and should be timed out. expires: time.Time, // The starting offset within the file. offset: int, // Number of bytes to send. If set to SEND_ENTIRE_FILE, the file size is retrieved // automatically and this field is updated to reflect the full size. nbytes: int, // If true, the callback is triggered periodically as data is sent. // The callback will continue to be called until `sent == nbytes` or an error occurs. progress_updates: bool, // Total number of bytes (so far if `progress_updates` is true). sent: int, // An error, if it occurred. Can be a filesystem or networking error. err: Send_File_Error, // Implementation specifics, private. _impl: _Send_File `fmt:"-"`, }
Send_File_Error ¶
Send_File_Error :: union { FS_Error, net.TCP_Send_Error, }
Related Procedures With Parameters
Specifics ¶
Specifics :: struct #raw_union { accept: Accept `raw_union_tag:"type=.Accept"`, close: Close `raw_union_tag:"type=.Close"`, dial: Dial `raw_union_tag:"type=.Dial"`, read: Read `raw_union_tag:"type=.Read"`, recv: Recv `raw_union_tag:"type=.Recv"`, send: Send `raw_union_tag:"type=.Send"`, write: Write `raw_union_tag:"type=.Write"`, timeout: Timeout `raw_union_tag:"type=.Timeout"`, poll: Poll `raw_union_tag:"type=.Poll"`, sendfile: Send_File `raw_union_tag:"type=.Send_File"`, open: Open `raw_union_tag:"type=.Open"`, stat: Stat `raw_union_tag:"type=.Stat"`, _remove: _Remove `raw_union_tag:"type=._Remove"`, _link_timeout: _Link_Timeout `raw_union_tag:"type=._Link_Timeout"`, _splice: _Splice `raw_union_tag:"type=._Splice"`, }
TCP_Recv_Error ¶
TCP_Recv_Error :: net.TCP_Recv_Error
TCP_Send_Error ¶
TCP_Send_Error :: net.TCP_Send_Error
TCP_Socket ¶
TCP_Socket :: net.TCP_Socket
Related Procedures With Parameters
Related Procedures With Returns
Timeout ¶
Timeout :: struct { // Duration after which the timeout expires. duration: time.Duration, // Implementation specifics, private. _impl: _Timeout `fmt:"-"`, }
UDP_Recv_Error ¶
UDP_Recv_Error :: net.UDP_Recv_Error
UDP_Send_Error ¶
UDP_Send_Error :: net.UDP_Send_Error
Write ¶
Write :: struct { // Handle to write to. handle: _Handle, // Buffer containing data to write. buf: []u8, // Offset to write to. offset: int, // Whether to write until the buffer is fully written or an error occurs. all: bool, // When this operation expires and should be timed out. expires: time.Time, // Error, if it occurred. err: FS_Error, // Number of bytes written. written: int, // Implementation specifics, private. _impl: _Write `fmt:"-"`, }
Constants
FULLY_SUPPORTED ¶
FULLY_SUPPORTED: bool : _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.
IP4_Any ¶
IP4_Any: net.IP4_Address : net.IP4_Any
IP4_Loopback ¶
IP4_Loopback: net.IP4_Address : net.IP4_Loopback
IP6_Any ¶
IP6_Any: net.IP6_Address : net.IP6_Any
IP6_Loopback ¶
IP6_Loopback: net.IP6_Address : net.IP6_Loopback
MAX_USER_ARGUMENTS ¶
MAX_USER_ARGUMENTS: int : #config(NBIO_MAX_USER_ARGUMENTS, 4)
The maximum size of user arguments for an operation, can be increased at the cost of more RAM.
NO_TIMEOUT ¶
NO_TIMEOUT: time.Duration : -1
Permissions_All ¶
Permissions_All :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All
Read, write, and execute permissions for user, group, and others.
Permissions_Default_Directory ¶
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 ¶
Permissions_Default_File :: Permissions_Read_All + Permissions_Write_All
Default permissions used when creating a file (read and write for everyone).
Permissions_Execute_All ¶
Permissions_Execute_All :: Permissions{.Execute_User, .Execute_Group, .Execute_Other}
Convenience permission sets.
Permissions_Read_All ¶
Permissions_Read_All :: Permissions{.Read_User, .Read_Group, .Read_Other}
Permissions_Read_Write_All ¶
Permissions_Read_Write_All :: Permissions_Read_All + Permissions_Write_All
Read and write permissions for user, group, and others.
Permissions_Write_All ¶
Permissions_Write_All :: Permissions{.Write_User, .Write_Group, .Write_Other}
SEND_ENTIRE_FILE ¶
SEND_ENTIRE_FILE: int : -1
Variables
This section is empty.
Procedures
accept ¶
accept :: proc(socket: net.TCP_Socket, cb: Callback, timeout: time.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 ¶
accept_poly :: proc(socket: net.TCP_Socket, p: $T, cb: $C/proc(op: ^Operation, p: $T), timeout: time.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 ¶
accept_poly2 :: proc( socket: net.TCP_Socket, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), timeout: time.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 ¶
accept_poly3 :: proc( socket: net.TCP_Socket, p: $T, p2: $T2, p3: $T3, cb: $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), timeout: time.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 ¶
acquire_thread_event_loop :: proc() -> General_Error {…}
Initialize or increment the reference counted event loop for the current thread.
associate_handle ¶
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 ¶
associate_socket :: proc(socket: net.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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
create_socket :: proc(family: net.Address_Family, protocol: net.Socket_Protocol, l: ^Event_Loop = nil, loc := #caller_location) -> (socket: net.Any_Socket, err: net.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 ¶
create_tcp_socket :: proc(family: net.Address_Family, l: ^Event_Loop = nil, loc := #caller_location) -> (net.TCP_Socket, net.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 ¶
create_udp_socket :: proc(family: net.Address_Family, l: ^Event_Loop = nil, loc := #caller_location) -> (net.UDP_Socket, net.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
current_thread_event_loop ¶
current_thread_event_loop :: proc(loc := #caller_location) -> ^Event_Loop {…}
detach ¶
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 ¶
dial :: proc(endpoint: net.Endpoint, cb: Callback, timeout: time.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 ¶
dial_poly :: proc(endpoint: net.Endpoint, p: $T, cb: $C/proc(op: ^Operation, p: $T), timeout: time.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 ¶
dial_poly2 :: proc( endpoint: net.Endpoint, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), timeout: time.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 ¶
dial_poly3 :: proc( endpoint: net.Endpoint, p: $T, p2: $T2, p3: $T3, cb: $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), timeout: time.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
error_string ¶
error_string :: proc(err: union {net.Create_Socket_Error, net.Dial_Error, net.Listen_Error, net.Accept_Error, net.Bind_Error, net.TCP_Send_Error, net.UDP_Send_Error, net.TCP_Recv_Error, net.UDP_Recv_Error, net.Shutdown_Error, net.Interfaces_Error, net.Socket_Info_Error, net.Socket_Option_Error, net.Set_Blocking_Error, net.Parse_Endpoint_Error, net.Resolve_Error, net.DNS_Error, General_Error, FS_Error, }) -> string {…}
error_string_recv ¶
error_string_recv :: proc(recv_err: net.Recv_Error) -> string {…}
error_string_send ¶
error_string_send :: proc(send_err: net.Send_Error) -> string {…}
error_string_sendfile ¶
error_string_sendfile :: proc(send_err: Send_File_Error) -> string {…}
exec ¶
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 ¶
listen_tcp :: proc(endpoint: net.Endpoint, backlog: int = 1000, l: ^Event_Loop = nil, loc := #caller_location) -> (socket: net.TCP_Socket, err: net.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 ¶
next_tick :: proc(cb: Callback, l: ^Event_Loop = nil) -> ^Operation {…}
Schedules an operation that completes on the next event loop tick.
This is equivalent to timeout(0, ...).
next_tick_poly ¶
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 ¶
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 ¶
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 ¶
now :: proc() -> time.Time {…}
Returns the current time (cached at most at the beginning of the current tick).
num_waiting ¶
Returns the number of in-progress operations to be completed on the event loop.
open ¶
open :: proc( path: string, cb: Callback, mode: bit_set[File_Flag; int] = {.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 ¶
open_poly :: proc( path: string, p: $T, cb: $C/proc(op: ^Operation, p: $T), mode: bit_set[File_Flag; int] = {.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 ¶
open_poly2 :: proc( path: string, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), mode: bit_set[File_Flag; int] = {.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 ¶
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; int] = {.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 ¶
open_sync :: proc( path: string, dir: _Handle = CWD, mode: bit_set[File_Flag; int] = {.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 ¶
poll :: proc(socket: net.Any_Socket, event: Poll_Event, cb: Callback, timeout: time.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 ¶
poll_poly :: proc( socket: net.Any_Socket, event: Poll_Event, p: $T, cb: $C/proc(op: ^Operation, p: $T), timeout: time.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 ¶
poll_poly2 :: proc( socket: net.Any_Socket, event: Poll_Event, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), timeout: time.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 ¶
poll_poly3 :: proc( socket: net.Any_Socket, event: Poll_Event, p: $T, p2: $T2, p3: $T3, cb: $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), timeout: time.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 ¶
prep_accept :: proc(socket: net.TCP_Socket, cb: Callback, timeout: time.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 ¶
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 ¶
prep_dial :: proc(endpoint: net.Endpoint, cb: Callback, timeout: time.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 ¶
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 ¶
prep_open :: proc( path: string, cb: Callback, mode: bit_set[File_Flag; int] = {.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 ¶
prep_poll :: proc(socket: net.Any_Socket, event: Poll_Event, cb: Callback, timeout: time.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 ¶
prep_read :: proc( handle: _Handle, offset: int, buf: []u8, cb: Callback, all: bool = false, timeout: time.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 ¶
prep_recv :: proc( socket: net.Any_Socket, bufs: [][]u8, cb: Callback, all: bool = false, timeout: time.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 ¶
prep_send :: proc( socket: net.Any_Socket, bufs: [][]u8, cb: Callback, endpoint: net.Endpoint = {}, all: bool = true, timeout: time.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 ¶
prep_sendfile :: proc( socket: net.TCP_Socket, file: _Handle, cb: Callback, offset: int = 0, nbytes: int = SEND_ENTIRE_FILE, progress_updates: bool = false, timeout: time.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 ¶
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 ¶
prep_timeout :: proc(duration: time.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 ¶
prep_write :: proc( handle: _Handle, offset: int, buf: []u8, cb: Callback, all: bool = true, timeout: time.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 ¶
read :: proc( handle: _Handle, offset: int, buf: []u8, cb: Callback, all: bool = false, timeout: time.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 ¶
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 ¶
read_poly :: proc( handle: _Handle, offset: int, buf: []u8, p: $T, cb: $C/proc(op: ^Operation, p: $T), all: bool = false, timeout: time.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 ¶
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: time.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 ¶
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: time.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 ¶
reattach :: proc(op: ^Operation) {…}
Reattach an operation to the package's lifetime management.
recv ¶
recv :: proc( socket: net.Any_Socket, bufs: [][]u8, cb: Callback, all: bool = false, timeout: time.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 ¶
recv_poly :: proc( socket: net.Any_Socket, bufs: [][]u8, p: $T, cb: $C/proc(op: ^Operation, p: $T), all: bool = false, timeout: time.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 ¶
recv_poly2 :: proc( socket: net.Any_Socket, bufs: [][]u8, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), all: bool = false, timeout: time.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 ¶
recv_poly3 :: proc( socket: net.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: time.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 ¶
release_thread_event_loop :: proc() {…}
Destroy or decrease the reference counted event loop for the current thread.
remove ¶
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 ¶
run :: proc() -> General_Error {…}
Runs the event loop by ticking in a loop until there is no more work to be done.
run_until ¶
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 ¶
send :: proc( socket: net.Any_Socket, bufs: [][]u8, cb: Callback, endpoint: net.Endpoint = {}, all: bool = true, timeout: time.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 ¶
send_poly :: proc( socket: net.Any_Socket, bufs: [][]u8, p: $T, cb: $C/proc(op: ^Operation, p: $T), endpoint: net.Endpoint = {}, all: bool = true, timeout: time.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 ¶
send_poly2 :: proc( socket: net.Any_Socket, bufs: [][]u8, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: $T, p2: $T2), endpoint: net.Endpoint = {}, all: bool = true, timeout: time.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 ¶
send_poly3 :: proc( socket: net.Any_Socket, bufs: [][]u8, p: $T, p2: $T2, p3: $T3, cb: $C/proc(op: ^Operation, p: $T, p2: $T2, p3: $T3), endpoint: net.Endpoint = {}, all: bool = true, timeout: time.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 ¶
sendfile :: proc( socket: net.TCP_Socket, file: _Handle, cb: Callback, offset: int = 0, nbytes: int = SEND_ENTIRE_FILE, progress_updates: bool = false, timeout: time.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 ¶
sendfile_poly :: proc( socket: net.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: time.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 ¶
sendfile_poly2 :: proc( socket: net.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: time.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 ¶
sendfile_poly3 :: proc( socket: net.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: time.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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
tick :: proc(timeout: time.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 ¶
timeout :: proc(duration: time.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 ¶
timeout_poly :: proc(dur: time.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 ¶
timeout_poly2 :: proc(dur: time.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 ¶
timeout_poly3 :: proc( dur: time.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 ¶
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 ¶
write :: proc( handle: _Handle, offset: int, buf: []u8, cb: Callback, all: bool = true, timeout: time.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 ¶
write_poly :: proc( handle: _Handle, offset: int, buf: []u8, p: $T, cb: $C/proc(op: ^Operation, p: $T), all: bool = true, timeout: time.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 ¶
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: time.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 ¶
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: time.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
This section is empty.
Source Files
Generation Information
Generated with odin version dev-2026-01 (vendor "odin") Windows_amd64 @ 2026-01-16 21:14:59.690710400 +0000 UTC