A small async runtime written in Rust as a learning project.
The runtime consists of three primary components:
- An
Executorthat polls runnable futures. - A
Reactorbuilt on Linuxepoll. - A custom
Wakerimplementation that requeues tasks when they become runnable again.
The goal of the project is to learn the basic relationship between futures, executors, wakers, and an event-driven reactor.
The executor owns a queue of runnable tasks.
Each task is stored as:
Arc<Mutex<Task>>The executor repeatedly:
- Removes a task from the front of the queue.
- Creates a custom waker for that task.
- Polls the future.
- Continues if the future returns
Poll::Pending. - Drops the task if it returns
Poll::Ready(()).
If no runnable tasks exist, the executor blocks inside the reactor until an I/O event occurs.
The executor terminates when:
- The runnable task queue is empty.
- The reactor has no registered pending I/O operations.
The reactor is responsible for waiting on operating system events.
Internally it maintains:
HashMap<RawFd, Waker>and an epoll instance.
When a future cannot make progress because it is waiting on I/O, it registers:
- The file descriptor to monitor.
- The task's waker.
The reactor then:
- Waits inside
epoll_wait. - Receives readiness notifications from the kernel.
- Looks up the corresponding waker.
- Wakes the associated task.
- Removes the registration from its internal table.
Currently the reactor watches for readable events using EPOLLIN.
The runtime provides a custom implementation of Rust's RawWaker.
Each waker stores:
struct WakerData {
queue: Arc<Mutex<VecDeque<Arc<Mutex<Task>>>>>,
task: Arc<Mutex<Task>>,
}When a task is woken:
- The task is pushed back into the executor queue.
- The executor will poll it again during a later iteration.
The implementation provides:
clonewakewake_by_refdrop
through a custom RawWakerVTable.
A task is simply a boxed future:
pub struct Task {
pub task: Pin<Box<dyn Future<Output = ()>>>,
}The runtime only supports futures with:
Output = ()This runtime currently targets Linux.
The reactor depends on:
epoll_create1epoll_ctlepoll_wait
and therefore is not portable to non-Linux platforms in its current form.
This project intentionally implements only a minimal subset of functionality.
Current limitations include:
- Linux-only implementation.
- No timer support.
- No sleep future.
- Single-threaded executor.
- No task cancellation.
- No task joining or result retrieval.
- No work-stealing scheduler.
- No support for futures returning values.
- Reactor only handles readiness notifications and does not provide higher-level async abstractions.
- Heavy use of
Mutexeven though execution is single-threaded. - Panic-based error handling for system call failures.
- No graceful handling of closed or invalid file descriptors.
- No executor metrics, tracing, or debugging facilities.
src/
├── executor.rs
├── reactor.rs
├── types.rs
└── waker.rs
This async-runtime was supposed to be a learning project and will not be recieving any further feature updates.