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:
| Resource | Operations |
|---|---|
SocketStreamReader | read returns an owned chunk; read_into and read_vectored use borrowed parser storage. |
SocketStreamWriter | write and write_vectored make borrowed transfers; submit accepts owned output that progresses independently, and flush waits for all accepted bytes. |
SocketPacketReader | read returns an owned message with source metadata; borrowed forms fill caller storage and report truncation. |
SocketPacketWriter | Send 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.
| Capability | Contract |
|---|---|
Clock | Monotonic observations, cancellable relative or absolute waits, and operation timeouts. |
Spawn | Task dispatch with implementation-associated, owning completion handles. |
Blocking | Bounded admission of owned synchronous work. |
ProcessWait | Individual child and Unix process-group status waits with cooperative cancellation. |
Signals | Notification subscriptions with implementation-associated guards and signal identifiers. |
BufferPooling | Shareable bounded storage with retained immutable views and cancellable capacity waits. |
| Extension capabilities | Typed 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 trueThe 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§
- Address
Hints - Typed hints passed to the resolver. Defaults request either IP family, any socket type/protocol, and no flags.
- Address
Info - An owned IP endpoint and its socket creation parameters. Obtain its domain with
SocketDomain::from(info.address); pass its type and protocol directly tosocket_open. - Address
Resolve Error - Resolver-specific details stored inside
OperationError::Io. Recover this value withio_error.get_ref().and_then(|error| error.downcast_ref::<AddressResolveError>()). - Buffer
Lease - 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.
- Buffer
Pool Options - 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.
- Buffer
Slice - An owned view into initialized storage. Dropping it drops its owner;
into_innerrecovers the complete buffer after an operation returns it. - Cancellation
- A runtime-independent, cooperative cancellation signal.
- Cancelled
- An operation observed a cooperative cancellation request.
- File
Options - 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.
- Frozen
Buffer - 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.
- Heap
Buffer Pool - 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.
- IoBuffers
Mut - 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. - Owned
Socket Recv Message - A received payload owner paired with portable receive metadata. Other message implementations may retain their backend’s native metadata instead.
- Process
Wait Flags - Selection of child state changes. The default waits for termination.
- Process
Wait Result - One child’s status. Only a termination status means the child has exited.
- Socket
Keepalive - 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. - Socket
Recv Flags - Portable input flags for socket receive operations.
- Socket
Recv Result - Metadata from one receive. Only
bytesbytes, spread across the buffers in order, were written; their initialized lengths remain unchanged. - Socket
Reuse Address - Boolean
SO_REUSEADDR. Set before binding when required by the application. - Socket
Send Flags - Portable input flags for socket send operations. Additional platform-specific flags belong in extension capabilities.
- TcpNo
Delay - 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§
- Address
Resolve Error Kind - Portable classification of resolver failures. Native error codes remain available separately and are not errno values.
- Address
Service - A numeric port or a service name interpreted by the resolver’s service database. Named services can resolve differently for different transports.
- Advice
Mode - 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.
- Allocation
Mode - How file-space allocation affects the logical file length.
- Blocking
Error - Blocking work could not be admitted. Job completion separately reports
TaskError. - File
Type - The portable classification of a filesystem object. Platform metadata can distinguish additional kinds, such as Unix devices, sockets, and FIFOs.
- Operation
Error - Cooperative cancellation is distinct from an operating-system error.
- Socket
Address - An IP endpoint, compatible with standard-library socket addresses. An internet socket address, either IPv4 or IPv6.
- Socket
Domain - The address family of an IP socket.
- Socket
Protocol - An explicit IP transport protocol. Pass
Nonetosocket_openfor the operating system default for the domain and type. - Socket
Type - The transport semantics requested when opening a socket.
- Spawn
Error - A task could not be registered with its scheduler.
- Sync
Mode - The file data and metadata requested by
FileSync::file_sync. A backend may provide stronger synchronization than requested. - Task
Error - A task ended without producing its normal output.
- Timeout
Error - Failure of a clock timeout, separate from the wrapped operation’s own output.
Traits§
- Address
Info Collection - 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.
- Address
Info View - 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.
- Address
Resolution - 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.
- Buffer
Pool - 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.
- Buffer
Pooling - 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.
- File
Advice - Optional file advice capability, following Linux
posix_fadvisesemantics. - File
Allocate - Optional file-space reservation capability, with Linux
fallocatesemantics for ordinary allocation andKEEP_SIZE. - File
Close - Close exclusively owned file resources with completion or admission-only semantics.
- File
Metadata - 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. - File
Open - Create file resources through the chosen scheduler.
- File
Operation - Shared resource type for file operations provided by a scheduler.
- File
Reader - 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. - File
Reading - Construct a sequential file reader bound to this scheduler. Backends select the handle representation; protocols need no monitor or raw dispatch capabilities.
- File
Seek - Inspect or reposition a file resource’s shared cursor.
- File
Stat - Query owned metadata for an already-open file resource.
- File
Sync - Synchronize file contents and metadata through the chosen scheduler.
- File
Truncate - Change the logical length of an already-open file resource.
- File
Writer - 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. - File
Writing - 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.
- IoBuf
Mut - Owned writable storage. Operations fill its existing initialized length; they never expose uninitialized capacity or change the buffer length.
- IoBuf
Sequence - 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.
- IoBuf
Sequence Mut - 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.
- Process
Wait - Wait for a child process to change state without blocking an executor worker.
- Receive
Buffer - 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.
- Socket
Accept - Accept one connection from a listening socket.
- Socket
Address View - 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.
- Socket
Bind - Bind an existing socket to a local IP address.
- Socket
Close - Consume and close an exclusively owned socket through the scheduler.
- Socket
Connect - Connect an existing socket to a peer IP address.
- Socket
GetOption - Read a typed socket option. See
SocketOptionsfor the shared option contract; the opposite operation is not required. - Socket
Listen - Put an existing socket into listening mode.
- Socket
Local Address - Inspect the local IP address of a socket.
- Socket
Open - Create an unbound IP socket through the scheduler.
- Socket
Operation - 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.
- Socket
Option - A typed socket-option identifier. This describes its value, not how an operating system represents or accesses it.
- Socket
Options - Convenience aggregate of
SocketGetOption<O>andSocketSetOption<O>, automatically implemented for schedulers providing both operations for an option. Generic consumers require only the options they use, such asS: SocketOptions<TcpNoDelay>. - Socket
Packet Reader - 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.
- Socket
Packet Reading - Construct sequential packet input bound to this scheduler. Backends choose the static reader and completed message representation without exposing their receive mechanism.
- Socket
Packet Writer - 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.
Noneuses the connected peer. - Socket
Packet Writing - 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.
- Socket
Peer Address - Inspect the connected peer address of a socket.
- Socket
Recv Message - 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.
- Socket
Recv Message Mut - A completed message with exclusively writable payload storage. Immutable receive implementations need not implement this capability.
- Socket
Registration - 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.
- Socket
SetOption - Set a typed socket option. See
SocketOptionsfor the shared option contract; the opposite operation is not required. - Socket
Shutdown - Shut down one or both directions of a socket through the scheduler.
- Socket
Stream Reader - 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.
- Socket
Stream Reading - 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.
- Socket
Stream Writer - 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.
- Socket
Stream Writing - 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§
- Buffer
Result - The operation result and original owned buffer, returned on success, error, or cancellation.
- Operation
Result - An operation’s result, preserving cancellation separately from I/O failure.