Foundational concurrency APIs for Rust projects in the Socketry ecosystem.
The socketry package re-exports socketry-executor: owned asynchronous
tasks, explicit child barriers, and a futures executor with multiple workers
and work stealing. Tasks use ordinary future polling and have no private
coroutine stacks.
[dependencies]
socketry = "0.1"use socketry::{Scheduler, yield_now};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let scheduler = Scheduler::with_workers(4)?;
let task = scheduler.spawn(async {
yield_now().await;
42
})?;
let answer = scheduler.block_on(task)?;
assert_eq!(answer, 42);
Ok(())
}Workers start when the scheduler is constructed. spawn accepts
Send + 'static futures and returns an awaitable result handle. Dropping that
handle leaves the task owned by its scheduler or barrier. Dropping the
scheduler requests cancellation and joins workers when called outside a worker.
Use scheduler.barrier() to own children explicitly. Both schedulers and
barriers implement Spawn. barrier.wait().await waits for completion;
barrier.stop().await closes the barrier, cancels children, and waits for their
synchronous destructors. Dropping a barrier requests cancellation without
waiting. Observe individual results and panics through task handles.
Scheduler::current() and Task::current() provide contextual lookup while
tasks run. Use .await to suspend; synchronous blocking calls occupy a worker.
See the executor package for scheduling, ownership, cancellation and allocation details. An executable example is:
cargo run --package socketry-executor --example work_stealingGeneric code can accept Network, FileIo, Clock, and Spawn capabilities.
Socketry and the optional Tokio adapter implement these contracts with concrete
future and resource types. Import the traits to call their methods.
| Cargo configuration | Implementation |
|---|---|
Default (native) |
Socketry tasks; epoll, kqueue or Windows IOCP/AFD socket readiness through async-io. |
features = ["io-uring"] on Linux |
Native completion reads/writes through an io_uring selector. |
features = ["tokio"] |
Also expose socketry::scheduler::tokio::Scheduler, adapting an existing Tokio runtime. |
default-features = false, features = ["tokio"] |
Tokio adapter without Socketry's native I/O dependencies. |
default-features = false |
Task executor and portable contracts, without I/O implementations. |
Socket registrations persist across operations and worker migration. Reads and
writes take a reusable owned Vec<u8> and return (io::Result<usize>, Vec<u8>).
Reads fill the buffer's existing length; allocate it with vec![0; capacity].
Operations may transfer fewer bytes than requested. Dropping a future can
abandon an operation that has already consumed or transmitted bytes.
Run the same TCP exchange with either runtime:
cargo run -p socketry-executor --example portable_io
cargo run -p socketry-executor --example portable_io --no-default-features --features tokio
# Linux native completion:
cargo run -p socketry-executor --example portable_io --features io-uringThe Tokio adapter needs a live runtime with I/O and time enabled. It preserves
explicit task/barrier ownership, and its asynchronous shutdown().await joins
task destruction. Passing its handle explicitly selects Tokio; Socketry's
Scheduler::current() continues to identify Socketry execution.
TCP connect/accept/read/write/readiness, positioned file reads/writes, and sleep are implemented. Regular files use blocking pools except for Linux io_uring. Windows socket readiness uses IOCP/AFD; native overlapped file operations are not implemented. Socketry currently uses async-io's shared readiness reactor and timers; the io-event timer port remains planned in the design guide.
The io_uring selector owns a dedicated thread, retains buffers until terminal
completions, and drains cancellation during shutdown. Connection setup and
readiness waits still use async-io. Kernel support is probed when the selector
is first needed; failures are returned without silently falling back. Operation
pooling, registered buffers, UDP, arbitrary descriptor APIs, and a local
!Send task executor remain future work.
The former coroutine implementation is preserved on branch coroutine, at
commit b520f3d. Its native sources, stack allocation, nested synchronous
wait and task transfer are absent from the future executor.
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. See the
Cargo publishing guide.
See releases.md for the full release history.
- Create or update GitHub Releases after successful crates.io publication.
- Move implementation and design guidance into the package's public context.
- Add Bake Agent Context tasks to the repository's development workspace.
- socketry — Foundational concurrency APIs for Socketry
Please open an issue or pull request on GitHub.
Before contributing, read agents.md and the relevant context files it links. If agents.md is missing or out of date, run cargo bake agent:context:install to install context from dependencies and update the index.
This crate includes an implementation guide and a
design guide. The private bake/ package links Bake Cargo,
Bake Agent Context, and their companion task crates. Its version-bump hook
updates the license, release notes, and generated Readme sections. Install
dependency context into the repository with:
cargo bake agent:context:installInstall the launcher once with cargo install socketry-cargo-bake --locked.
The generated .agents/context/ directory is ignored by Git. Repository-only
conventions remain under .agents/ in the source checkout; publishing guidance
is included in Bake Cargo agent context.