Skip to main content

Crate base_scheduler

Crate base_scheduler 

Source
Expand description

Explicit, runtime-independent scheduler capabilities for protocol libraries.

§base-scheduler

Explicit scheduler capabilities for reusable Rust protocol libraries. Applications choose an execution environment; libraries ask for the operations they need.

The root crate defines interfaces and runtime-independent support. It contains no executor, reactor, operating-system I/O implementation, or runtime adapter. The initial API is extracted from Socketry.

The minimum supported Rust version is 1.87. Socket reader/writer factories use precise lifetime captures: their handles borrow the scheduler, not the temporary socket reference, allowing a connection to own its socket and directional handles together.

The workspace also contains seven companion crates, released together with the interface:

  • base-scheduler-conformance: reusable capability-specific assertions for backend development dependencies.
  • base-scheduler-direct: reference implementations of tasks, clocks, native address resolution, file/socket operations, and platform-supported signals and filesystem extensions, with explicit service ownership and bounded syscall admission.
  • base-scheduler-tokio: an adapter for an explicitly selected Tokio runtime, preserving owning task handles, owned I/O, cancellation, and bounded native-work admission.
  • base-scheduler-native: Socketry’s work-stealing executor and native readiness I/O, with Base ownership and shutdown semantics.
  • base-scheduler-selector: independent I/O lifecycle contracts and the portable readiness selector.
  • base-scheduler-iouring: Linux completion file and socket I/O with a separately owned event driver and explicit readiness fallback.
  • base-scheduler-timers: runtime-independent batched timers, reusable sleep registrations, and deadline notifications.

§Usage

Add the interface with cargo add base-scheduler. Applications select a companion backend; reusable libraries depend on the interface capabilities they use.

Construct readers and writers from the scheduler once, then pass cancellation to their operations. A protocol object can retain these bound capabilities alongside its parser and protocol state:

use base_scheduler::{Cancellation, OperationResult, SocketStreamReader};

struct Body<Reader> {
    reader: Reader,
}

impl<Reader: SocketStreamReader> Body<Reader> {
    async fn read_into(
        &mut self,
        buffer: &mut [u8],
        cancellation: &Cancellation,
    ) -> OperationResult<usize> {
        self.reader.read_into(buffer, cancellation).await
    }
}

Create the reader with scheduler.socket_stream_reader(&socket). Its scheduler is fixed at construction; cancellation belongs to each call. Moving the protocol object or its future between workers leaves registration, routing, and retirement to the selected backend.

§Socket and file I/O

The four socket handles are the normal application interface:

ResourceOperations
SocketStreamReaderread returns an owned chunk; read_into and read_vectored use borrowed parser storage.
SocketStreamWriterwrite and write_vectored make borrowed transfers; submit accepts owned output that progresses independently, and flush waits for all accepted bytes.
SocketPacketReaderread returns an owned message with source metadata; borrowed forms fill caller storage and report truncation.
SocketPacketWriterSend one packet from borrowed scalar/vector storage or an owned buffer, with an optional destination.

Construct them through scheduler.socket_stream_reader, socket_stream_writer, socket_packet_reader, and socket_packet_writer. Reuse one handle per sequential execution, with separate readers and writers for concurrent tasks. Borrowed-only readers do not allocate a receive pool. Owned reads initialize a default pool lazily, or use a shared pool supplied to socket_stream_reader_with_pool or socket_packet_reader_with_pool. Retained chunks can freeze into immutable views and move between tasks; their final owner returns storage for reuse.

scheduler.file_reader(&file) and scheduler.file_writer(&file) provide the same construction pattern for reusable owned-buffer file I/O. read and write use the OS cursor; read_at and write_at take explicit offsets. Handles have no private logical file position. File operations return the original owner alongside success, error, or cancellation. Join independent read and write futures to overlap a file pipeline.

Call close().await on each reader and writer before dropping it and exclusively closing its resource. Flush successful stream output first. Close has no cancellation argument and establishes backend retirement; dropping a handle is not an awaited cleanup barrier.

See the I/O usage guide, interface reference, and runnable examples for complete loops, buffer retention, partial transfers, and cleanup. The backend selects persistent readiness, request reuse, and buffer registration behind these handles. Adapters implement the same resource traits and keep dispatch, registration, and retirement state private.

§Other capabilities

File and socket lifecycle operations remain explicit scheduler capabilities: open, bind, listen, connect, accept, options, metadata, synchronization, and close. Protocol libraries require the individual capabilities they use; there is no universal scheduler requirement.

CapabilityContract
ClockMonotonic observations, cancellable relative or absolute waits, and operation timeouts.
SpawnTask dispatch with implementation-associated, owning completion handles.
BlockingBounded admission of owned synchronous work.
ProcessWaitIndividual child and Unix process-group status waits with cooperative cancellation.
SignalsNotification subscriptions with implementation-associated guards and signal identifiers.
BufferPoolingShareable bounded storage with retained immutable views and cancellable capacity waits.
Extension capabilitiesTyped socket options, address resolution, standard TCP resource registration, file advice, and allocation.

Operation futures use static dispatch and are Send; no boxed future or runtime-selection feature is required. Spawned futures and outputs are Send + 'static. Backend resource types and construction establish compatibility.

Cancellation is a runtime-independent cooperative signal. Clones share state, children inherit ancestor cancellation, and dropping a signal does not cancel it. Pre-cancellation prevents cancellable operation submission; successful progress can win a concurrent request. Cancellation does not roll back bytes or cursor changes. A task handle owns its execution lifetime: await it to observe completion, or drop it to request destruction after any active poll returns. Keep the scheduler and its drivers alive while accepted work retires.

§Development

Install the launcher with cargo install bake --locked. The private bake/ workspace member supplies the shared Base development tasks:

cargo bake --locked test:coverage --all-targets true --all-features true

The tests cover runtime-independent support, generic composition, reusable conformance assertions, and the Direct, Tokio, Native, readiness, and io_uring backends.

§Releasing

Prepare a release with cargo bake cargo:version:patch (or minor, major, or bump --version X.Y.Z), then run cargo bake cargo:release and open a pull request. After review and merge, GitHub Actions publishes the release when the configured crates-io environment approves it. Follow the shared Releasing skill for the standard process.

§Releases

Version v0.2.0 corrects socket-handle lifetime captures and requires Rust 1.87. See the release notes.

§See Also

See the design and behavioral contracts for resource compatibility, shutdown, cancellation boundaries, and extraction decisions.

The TCP echo benchmark compares pure Tokio, the Tokio scheduler adapter, and Native with per-worker io_uring rings using separate server and client processes.

§Contributing

Please open an issue or pull request on GitHub.

§Agent Context

Run cargo bake agent:context:install to install shared context and skills. Use cargo bake agent:context:list and cargo bake agent:context:show to discover guidance. Follow agents.md and the relevant skills under .agents/skills/.

Structs§

AddressHints
Typed hints passed to the resolver. Defaults request either IP family, any socket type/protocol, and no flags.
AddressInfo
An owned IP endpoint and its socket creation parameters. Obtain its domain with SocketDomain::from(info.address); pass its type and protocol directly to socket_open.
AddressResolveError
Resolver-specific details stored inside OperationError::Io. Recover this value with io_error.get_ref().and_then(|error| error.downcast_ref::<AddressResolveError>()).
BufferLease
An exclusive writable pool lease. Its initialized length can be shortened after a read, without copying or borrowing the receiver. Drop returns storage to the pool; an I/O backend must retain this owner until its access retires. A lease keeps its backing slab alive even after the pool is dropped.
BufferPoolOptions
Usable payload capacity and alignment, independent of kernel registration strategy. Backends must satisfy these requirements or return an error; backend metadata and allocation padding may require additional memory.
BufferSlice
An owned view into initialized storage. Dropping it drops its owner; into_inner recovers the complete buffer after an operation returns it.
Cancellation
A runtime-independent, cooperative cancellation signal.
Cancelled
An operation observed a cooperative cancellation request.
FileOptions
Portable regular-file opening options. Fields are visible to alternative implementations, including simulated filesystems. Append mode is omitted: positioned writes must target the supplied offset.
FrozenBuffer
An immutable pool-backed chunk. Cloning or retaining a range shares its existing allocation; the final view returns the slot to the pool. Views keep the backing slab alive even after the pool is dropped, so parsers may choose to copy unusually long-lived fragments.
HeapBufferPool
A bounded, shareable collection of stable initialized slots in one contiguous slab. Construction reserves all payload storage; acquiring, freezing, slicing, and returning leases allocate no payload or reference-count wrappers.
IoBuffers
An owned scatter/gather package with I/O vectors prepared once at construction. The vector allocation and source owners are reused between operations; payload bytes are never copied.
IoBuffersMut
An owned writable scatter/gather package with I/O vectors prepared once. Like IoBuffers, it retains the complete source sequence and supports explicit advancement after retirement.
OwnedSocketRecvMessage
A received payload owner paired with portable receive metadata. Other message implementations may retain their backend’s native metadata instead.
ProcessWaitFlags
Selection of child state changes. The default waits for termination.
ProcessWaitResult
One child’s status. Only a termination status means the child has exited.
SocketKeepalive
Boolean SO_KEEPALIVE: enable or disable OS keepalive probes, using the system’s timing defaults. Probe intervals, counts, and application-level liveness policies are separate concerns.
SocketRecvFlags
Portable input flags for socket receive operations.
SocketRecvResult
Metadata from one receive. Only bytes bytes, spread across the buffers in order, were written; their initialized lengths remain unchanged.
SocketReuseAddress
Boolean SO_REUSEADDR. Set before binding when required by the application.
SocketSendFlags
Portable input flags for socket send operations. Additional platform-specific flags belong in extension capabilities.
TcpNoDelay
Boolean TCP_NODELAY: disable Nagle’s algorithm when true. Valid for TCP sockets; this does not promise one packet per write or confirmation of peer receipt.

Enums§

AddressResolveErrorKind
Portable classification of resolver failures. Native error codes remain available separately and are not errno values.
AddressService
A numeric port or a service name interpreted by the resolver’s service database. Named services can resolve differently for different transports.
AdviceMode
A file access or cache-management hint. Advice does not change the file’s contents, size, or cursor, and the operating system may ignore it.
AllocationMode
How file-space allocation affects the logical file length.
BlockingError
Blocking work could not be admitted. Job completion separately reports TaskError.
FileType
The portable classification of a filesystem object. Platform metadata can distinguish additional kinds, such as Unix devices, sockets, and FIFOs.
OperationError
Cooperative cancellation is distinct from an operating-system error.
SocketAddress
An IP endpoint, compatible with standard-library socket addresses. An internet socket address, either IPv4 or IPv6.
SocketDomain
The address family of an IP socket.
SocketProtocol
An explicit IP transport protocol. Pass None to socket_open for the operating system default for the domain and type.
SocketType
The transport semantics requested when opening a socket.
SpawnError
A task could not be registered with its scheduler.
SyncMode
The file data and metadata requested by FileSync::file_sync. A backend may provide stronger synchronization than requested.
TaskError
A task ended without producing its normal output.
TimeoutError
Failure of a clock timeout, separate from the wrapped operation’s own output.

Traits§

AddressInfoCollection
An owned resolver result whose representation is chosen by the backend. Borrowed entry views remain valid only while the result is borrowed. Iteration must preserve candidate ordering, duplicates, and native socket parameters without requiring a copied collection or per-entry reference counts.
AddressInfoView
Portable accessors for a resolved IP endpoint and its socket creation parameters. A view may borrow a native resolver entry; accessing one field need not copy or normalize the others.
AddressResolution
Optional IP endpoint resolution, independent of socket creation and connection. Implementations may use a system resolver, an asynchronous resolver, or a deterministic table.
Blocking
Optional scheduler capability for owned synchronous work on blocking threads.
BufferPool
A bounded, shareable source of exclusively writable, stable receive storage. Clones share the same capacity. Completed buffers and their frozen views retain storage independently of pool handles, receivers, and polling threads; the final owner makes that slot reusable.
BufferPooling
Construct a backend-selected pool with portable ownership semantics. Applications choose the payload budget and alignment; implementations choose allocation and registration strategy. Pool construction performs no I/O on application resources.
Clock
Monotonic time and cooperative waits in one scheduler’s clock domain.
FileAdvice
Optional file advice capability, following Linux posix_fadvise semantics.
FileAllocate
Optional file-space reservation capability, with Linux fallocate semantics for ordinary allocation and KEEP_SIZE.
FileClose
Close exclusively owned file resources with completion or admission-only semantics.
FileMetadata
Portable accessors for owned file status returned by crate::FileStat::file_stat. Each backend chooses its representation, so native results need no eager field conversion and simulations need no OS resources.
FileOpen
Create file resources through the chosen scheduler.
FileOperation
Shared resource type for file operations provided by a scheduler.
FileReader
Scheduler-bound, sequential access to a file’s readable direction. Construct through FileReading. Separate handles permit overlapping operations, but shared-cursor operations have no ordering guarantee across handles.
FileReading
Construct a sequential file reader bound to this scheduler. Backends select the handle representation; protocols need no monitor or raw dispatch capabilities.
FileSeek
Inspect or reposition a file resource’s shared cursor.
FileStat
Query owned metadata for an already-open file resource.
FileSync
Synchronize file contents and metadata through the chosen scheduler.
FileTruncate
Change the logical length of an already-open file resource.
FileWriter
Scheduler-bound, sequential access to a file’s writable direction. Construct through FileWriting. Operations preserve the file’s shared OS cursor; separate handles do not coordinate writes through aliases.
FileWriting
Construct a sequential file writer bound to this scheduler. Backends select the handle representation; protocols need no monitor or raw dispatch capabilities.
IoBuf
Owned, initialized storage suitable for completion-based I/O.
IoBufMut
Owned writable storage. Operations fill its existing initialized length; they never expose uninitialized capacity or change the buffer length.
IoBufSequence
An owned sequence of buffers for scatter/gather I/O. The collection itself may move; each buffer’s byte storage must remain stable. Arrays avoid allocating a separate collection, and custom owners can retain pooled storage.
IoBufSequenceMut
An owned sequence of writable buffers. Receiving fills their initialized byte ranges without resizing them or replacing their owners.
Notify
A synchronous destination for a notification value.
ProcessWait
Wait for a child process to change state without blocking an executor worker.
ReceiveBuffer
A uniquely writable completed receive that can become independently retained read-only storage. Backends choose the lease and shared representation; freezing consumes mutable access, and clones of the frozen owner keep its storage unavailable for reuse. Neither transition requires copying payload bytes.
Signals
Explicit signal subscriptions provided by a scheduler.
SocketAccept
Accept one connection from a listening socket.
SocketAddressView
An IP endpoint exposed by an address representation chosen by its provider. A view can borrow native metadata or refer to an already materialized portable address. The contract specifies the endpoint, without prescribing storage, copying, or allocation costs.
SocketBind
Bind an existing socket to a local IP address.
SocketClose
Consume and close an exclusively owned socket through the scheduler.
SocketConnect
Connect an existing socket to a peer IP address.
SocketGetOption
Read a typed socket option. See SocketOptions for the shared option contract; the opposite operation is not required.
SocketListen
Put an existing socket into listening mode.
SocketLocalAddress
Inspect the local IP address of a socket.
SocketOpen
Create an unbound IP socket through the scheduler.
SocketOperation
Shared resource type for socket operations provided by a scheduler. Implement this trait on the scheduler; all socket capabilities use this one associated type. No concrete OS descriptor or shared-ownership wrapper is required.
SocketOption
A typed socket-option identifier. This describes its value, not how an operating system represents or accesses it.
SocketOptions
Convenience aggregate of SocketGetOption<O> and SocketSetOption<O>, automatically implemented for schedulers providing both operations for an option. Generic consumers require only the options they use, such as S: SocketOptions<TcpNoDelay>.
SocketPacketReader
Sequential packet reception through a fixed execution service. Each read consumes at most one packet and preserves its sender and truncation metadata. Empty packets are messages, not EOF.
SocketPacketReading
Construct sequential packet input bound to this scheduler. Backends choose the static reader and completed message representation without exposing their receive mechanism.
SocketPacketWriter
Sequential packet sends through a fixed execution service. Every write is one send attempt, including empty packets; it never splits a packet into separate sends. None uses the connected peer.
SocketPacketWriting
Construct sequential packet output bound to this scheduler. Separate reader and writer handles permit concurrent reception and sending; backends can choose their own static writer.
SocketPeerAddress
Inspect the connected peer address of a socket.
SocketRecvMessage
An owned received stream chunk or datagram, with backend-associated payload storage and metadata. The message may move between workers and outlive its receiver and scheduler. Its accessors describe contents and ownership, without prescribing allocation, copying, registration, or receive strategy.
SocketRecvMessageMut
A completed message with exclusively writable payload storage. Immutable receive implementations need not implement this capability.
SocketRegistration
Optional interoperability with existing standard-library TCP resources. Streams and listeners become the same backend socket descriptor. Register once; the backend sets the nonblocking mode it needs. Do not change that mode through another handle. Simulated schedulers need not implement it.
SocketSetOption
Set a typed socket option. See SocketOptions for the shared option contract; the opposite operation is not required.
SocketShutdown
Shut down one or both directions of a socket through the scheduler.
SocketStreamReader
One sequential input lane on a stream socket, bound to its creating scheduler. Independent reader and writer handles may operate concurrently. Backend registration and worker migration are internal details; moving a handle never changes its scheduler.
SocketStreamReading
Construct sequential stream input bound to this scheduler. Backends can substitute their own static reader while keeping protocol code independent of registration and receive mechanisms.
SocketStreamWriter
One ordered output lane on a stream socket, bound to its creating scheduler. Independent readers may operate concurrently. Separate writers or direct socket aliases do not share this handle’s ordering.
SocketStreamWriting
Construct sequential stream output bound to this scheduler. Backends select a static writer without requiring protocols to choose registration or output-progress mechanisms. Construction performs no writes and rejects non-stream sockets.
Spawn
The common spawning contract for schedulers and their handles.
Timers
Experimental reusable timer capability for the timer benchmark. This is not a settled public contract.

Functions§

defer_cancel
Notify protected work of cancellation and continue awaiting its completion.

Type Aliases§

BufferResult
The operation result and original owned buffer, returned on success, error, or cancellation.
OperationResult
An operation’s result, preserving cancellation separately from I/O failure.