Skip to main content

Budget

Struct Budget 

Source
pub struct Budget { /* private fields */ }
Expand description

Tracks one run against its Limits.

A Budget is not Clone: it is one run’s, and a second one would be a second run. What is shared instead is Meter, the view of the same accounting that a safepoint charges through, and every task thread of the run holds one — ADR 0008 draws a task’s fuel from the run’s budget rather than giving each task one of its own, so there is still exactly one authoritative count of what the run spent. Share a Cancellation when another thread needs to stop the run.

max_call_depth is the one limit a budget does not itself enforce. Call depth is a property of one stack, and with a thread per task there is a stack per task, so the interpreter checks its own depth against Limits::max_call_depth; counting every task’s frames into one number would stop a shallow task because a sibling was deep.

Implementations§

Source§

impl Budget

Source

pub fn new(limits: Limits) -> Self

Tracks a run against limits, starting the deadline clock now.

Source

pub fn with_cancellation(limits: Limits, cancellation: Cancellation) -> Self

Tracks a run against limits, using a Cancellation the caller already holds a handle to, so it can be cancelled from elsewhere.

Source

pub fn meter(&self) -> Meter

This run’s accounting, in the handle a safepoint charges through.

A caller that will charge more than once holds on to what this answers: taking one costs an Arc clone, and charging through one costs no lock at all. Meter says where each backend takes its own and why that is where a run begins.

Source

pub fn cancellation(&self) -> Cancellation

The cancellation flag for this run. Clone and hand it to whoever may need to cancel the run from another thread.

Source

pub fn limits(&self) -> &Limits

The limits this budget was constructed with.

Source

pub fn safepoint(&self, fuel: u64) -> Result<(), Stopped>

Checks cancellation, the deadline, and fuel in one call. The interpreter calls this at safepoints: loop back edges, calls, and await. fuel is the cost of the work performed since the last safepoint.

Meter::safepoint is the whole of it. A backend on a per-instruction path holds a Meter and calls that instead of reaching a Budget through the registry’s lock; this is here for a caller that has a Budget in hand and charges once.

Source

pub fn spend(&self, fuel: u64)

Adds fuel to the run’s total without asking whether the run may continue. Meter::spend says when that is what a backend wants.

Source

pub fn charge_host_call(&self) -> Result<(), Stopped>

Charges one host call against the budget, failing before the call is dispatched if the run was cancelled, if its deadline has passed, or if the call would exceed max_host_calls.

A host call is a control point exactly as a safepoint is. ADR 0003 puts the controls at “loop back edges, calls, and await”, and a run whose work is waiting on a host reaches none of the other three: a deadline checked only in Cove code would not bound a program that spends its time inside calls. The clock is read on every call rather than every DEADLINE_CHECK_INTERVALth, because a host call already costs far more than reading it does.

Source

pub fn charge_task(&self) -> Result<(), Stopped>

Charges one task against the concurrency limit, refusing it before it is given a thread if the run already holds as many tasks as it may.

Every other limit stops a run for work it has already done. This one refuses work that has not started, because a thread is taken rather than spent: by the time a safepoint could observe it, the resource is already held. A refusal stops the run the way exhausted fuel does; a spawn that waited for a sibling to finish would be a scheduler, and ADR 0008 deliberately has no scheduling policy.

The check and the taking are one step, so two spawns racing for the last place cannot both be told there is one. That used to be the registry’s mutex; it is this compare-and-swap now, which holds however this is reached.

Source

pub fn release_task(&self)

Forgets a task whose end has been observed, so its place is free again.

A task ends by finishing, by failing, by being cancelled, or by breaking an invariant in its own thread, and all four reach the caller as a join. Releasing anywhere else would make this a limit on how many tasks a run may spawn in total rather than on how many it may hold at once.

Source

pub fn live_tasks(&self) -> u64

How many spawned tasks are alive right now: what the concurrency limit bounds, and what a stop reports.

Source

pub fn fuel_spent(&self) -> u64

Total fuel spent so far, for reporting.

Source

pub fn host_calls(&self) -> u64

Total host calls charged so far, including any that were then rejected for exceeding the limit, for reporting.

Source

pub fn elapsed(&self) -> Duration

Wall-clock time elapsed since the budget was created.

Source

pub fn to_runtime_error(&self, stopped: Stopped) -> RuntimeError

Converts why execution stopped into a RuntimeError naming the limit and its configured value, quoting ADR 0001’s position that these are runtime controls rather than termination proofs.

Trait Implementations§

Source§

impl Debug for Budget

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.