Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Eddy Tasks

Each spawned future is stored in one Box<Cell<F, S>>. Cell is repr(C) and contains three regions:

Header: state, vtable, ownership/instrumentation metadata, queue link
Core:   scheduler and Stage<F> (Running, Finished, or Consumed)
Trailer: join-handle waker

The scheduler holds a type-erased RawTask pointer. Its vtable knows how to poll, schedule, read output, shut down, and deallocate the concrete cell, so the queues do not need to be generic over every future type.

State Machine

Header::state packs flags into the low bits of one atomic word and the task reference count above them. The important transitions are:

spawn -> NOTIFIED + queued reference
queue -> RUNNING + remove NOTIFIED
poll Pending -> IDLE, or NOTIFIED when a wake raced with poll
poll Ready -> COMPLETE, then output is read by JoinHandle
abort -> CANCELLED; the owner finalizes the future safely

RUNNING prevents concurrent polls. NOTIFIED closes the lost-wakeup window: if a reactor or another task wakes a running task, the current poll observes the bit and submits another queue entry before becoming idle.

References

The initial task allocation accounts for the join handle and the initial run-queue entry. A waker clone adds a reference. By-value wake consumes its waker reference; wake_by_ref does not. The allocation is released only when all scheduler, join, and waker references are gone. Current-thread destruction is deferred to the owner when a non-owner drops the last usable reference.

The size-budget test in task/raw.rs guards the concrete Cell<F, S> layout without making the internal scheduler or allocation layout part of the public API.