I’ve worked on a handful of projects over the past years. As SourceHut and GitHub’s project discovery mechanisms are poor, I’ve decided to list them here, in order of relative importance.


smol is a small and fast async runtime for Rust.

It is designed to be easily compartmentalized, efficient and simple. A user with intermediate Rust programming experience should be able to understand the components of the runtime and how they interact with each other.

I am not the original author of smol; however, I am one of its primary maintainers. smol is composed of many smaller crates.

  • async-io is a reactor for asynchronous I/O primitives. It wraps around socket types (like TcpStream and UnixStream) and provides a unified interface for asynchronous I/O. It uses polling to poll for I/O events and converts them into a futures-based API.
  • blocking is a thread-pool that can transform blocking functions into asynchronous functions. This thread pool is flexible and only uses the number of threads that are needed. It can also turn Read, Write and Iterator types into asynchronous AsyncRead, AsyncWrite and Stream that uses this thread pool.
  • futures-lite is a lightweight set of combinators for futures, Streams and asynchronous I/O.
  • async-task provides a way to associate some state with a future such that it can be polled in a separate executor, while a Task handle is still held by the user. It is highly efficient, only uses a single allocation and has zero dependencies.
  • async-executor is the reference implementation of the asynchronous executor built on async-task. It supports multi-threaded execution, and is used by smol to execute tasks.
  • async-channel is an MPMC asynchronous channel that supports sending data between tasks.
  • async-lock is an implementation of locking primitives that can be awaited on.
  • async-fs is an async implementation of std::fs. It uses blocking to handle file system operations in an async way.
  • async-net is an async implementation of the std::net module. It provides TcpStream, TcpListener, UdpSocket and UnixStream types. It uses async-io for asynchronous I/O and blocking for DNS lookups.
  • async-process is an async wrapper around std::process. It listens for SIGCHLD in order to wait for inner process events in an async way. async-io is used for asynchronous I/O on pipes in Unix, and blocking is used on Windows.
  • async-signal allows for asynchronous signal waiting. It is used in async-process to wait for the SIGCHLD signal.
  • concurrent-queue is a lock-free MPMC queue. It is used to implement channels, task queues and other primitives.
  • event-listener is a fundamental building block for asynchronous primitives. Essentially, it allows non-blocking data structures to be transformed into asynchronous data structures, by having it wait for events to happen in other tasks. Under the hood it is a linked list of tasks waiting for an event to happen.
  • fastrand is a basic PRNG that provides good-enough randomness for many applications in smol.
  • parking blocks and unblocks threads. It is a version of std::thread::park without global variables and with a “signal” mechanism.
  • piper is a ring buffer that can send bytes between tasks. It is used to implement pipes in blocking.
  • polling is a portable but featureful around epoll, kqueue, IOCP and others. It allows for cross-platform polling of I/O events.