pub trait ConcurrentInvoke {
// Required methods
fn meta_of(&self, call: &ToolCall) -> Option<&ToolMeta>;
fn admit(&mut self, call: &ToolCall, t: TimeMs) -> Admitted;
fn tool(&self, ticket: &Ticket) -> Result<&dyn Tool, AxError>;
fn account(
&mut self,
call: &ToolCall,
ticket: Ticket,
answered: Result<ToolOutcome, AxError>,
) -> Result<ToolOutcome, AxError>;
// Provided methods
fn resolve_call(&self, call: ToolCall) -> ToolCall { ... }
fn ahead(&self, _call: &ToolCall) -> Option<&dyn Tool> { ... }
}Expand description
A wave’s tools in three stages, so the calls that only read can run at once while everything they decide stays in call order.
The leading run of calls whose tool declares Effect::Read is
admitted one call at a time, in call order; the tools of the calls it
clears then run at once, each on its own scoped thread; and every
answer is accounted one call at a time, in call order. The first
call with any other effect waits until every one of them has
answered, and from there the wave is serial. The Ledger sees the same
lines in the same order either way: results wait in a reorder buffer
and are written in call order.
A trait rather than three closures: admitting and accounting write
the same dedup table and taint that tool lends out, and three
closures cannot each borrow one bench.
Required Methods§
Sourcefn meta_of(&self, call: &ToolCall) -> Option<&ToolMeta>
fn meta_of(&self, call: &ToolCall) -> Option<&ToolMeta>
The registration of the call’s tool: its effect decides whether
the call is read-only, and tool_called copies its effect and
render (crates/runtime/spec/Turn.lean §8-51). None is a tool the bench does not
know, which is not read-only.
Sourcefn admit(&mut self, call: &ToolCall, t: TimeMs) -> Admitted
fn admit(&mut self, call: &ToolCall, t: TimeMs) -> Admitted
Stage one, serial in call order: whether the call may run, at the turn’s stamp. An answer that needs no tool (a replay, a door’s refusal) comes back here.
Sourcefn tool(&self, ticket: &Ticket) -> Result<&dyn Tool, AxError>
fn tool(&self, ticket: &Ticket) -> Result<&dyn Tool, AxError>
Stage two: the tool a cleared call runs on. It takes &self, so
every cleared call’s tool is lent out at once and invoked from
several threads; a tool is Sync where the implementor need not be.
Sourcefn account(
&mut self,
call: &ToolCall,
ticket: Ticket,
answered: Result<ToolOutcome, AxError>,
) -> Result<ToolOutcome, AxError>
fn account( &mut self, call: &ToolCall, ticket: Ticket, answered: Result<ToolOutcome, AxError>, ) -> Result<ToolOutcome, AxError>
Stage three, serial in call order: records what the tool answered and returns what the model reads back.
Provided Methods§
Sourcefn resolve_call(&self, call: ToolCall) -> ToolCall
fn resolve_call(&self, call: ToolCall) -> ToolCall
The call behind a call through call, resolved before anything
reads a registration (crates/runtime/Spec.lean §8-61).
Sourcefn ahead(&self, _call: &ToolCall) -> Option<&dyn Tool>
fn ahead(&self, _call: &ToolCall) -> Option<&dyn Tool>
The tool a read-only call would run on, lent out before the call
is admitted so it can start while the model is still generating.
What it returns reaches the model only if admit later clears the
same call. None, the default, starts nothing early.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl<F> ConcurrentInvoke for F
A closure is a tool face that answers every call as it admits it: it declares no effect, so its waves are serial. citysim and the tests that script a tool’s answer drive a run through this one.