Skip to main content

HotFn

Struct HotFn 

Source
pub struct HotFn<A, M, F>
where F: HotFunction<A, M>,
{ /* private fields */ }
Expand description

A hot-reloadable function: HotFn::call runs the newest version the jump table maps.

Implementations§

Source§

impl<A, M, F: HotFunction<A, M>> HotFn<A, M, F>

Source

pub const fn current(f: F) -> HotFn<A, M, F>

Wrap f, keyed on its call_it monomorphisation. Sound for any FnMut: a fn item, a closure of any size, or a function pointer (which then dispatches as one call_it shared by every pointer of that type; use HotFn::from_fn_ptr to key on the pointer itself).

Source

pub fn from_fn_ptr(f: F) -> HotFn<A, M, F>
where F: FnPointer<A, M>,

Wrap the function pointer f, keyed on its own value: the jump table maps the pointed-to function’s address to its patched version. F must be a non-higher-ranked fn(A, ..) -> R of up to nine arguments (FnPointer); wrap anything else with HotFn::current.

Source

pub fn call(&mut self, args: A) -> F::Return

Call the function with args.

In a debug build this is one jump-table lookup (see HotFn::try_call): the patched version runs when the installed table maps this function’s key, else the original. No stale-call detection, no retry; panics propagate untouched. A release build calls the function directly and never reads the table.

Source

pub fn ptr_address(&self) -> HotFnPtr

The address a call would currently reach: the jump table’s mapping for this function’s key when one is installed and maps it, else the key itself. The key is the call_it address, or for HotFn::from_fn_ptr the pointer’s value. A release build never reads the table and always reports the key.

A runtime that memoizes state across patches can compare it between patches: an unchanged address means the state “above” the function is still valid. Tracking it over time is the caller’s job.

Source

pub fn try_call(&mut self, args: A) -> Result<F::Return, Infallible>

Call the function with args through one jump-table lookup.

Debug builds only: the key (the call_it address, or for HotFn::from_fn_ptr the pointer’s value, with the aarch64 Android pointer tag stripped) is looked up in the installed table; a hit calls the patched address, a miss or an empty table calls the original, and the outcome is recorded for last_call_fell_through / fall_through_count / missed_keys; a hit is counted by seam_hits. A release build calls the function directly.

Never fails: the Result keeps subsecond’s call shape, and the error type is Infallible.

Source

pub unsafe fn try_call_with_ptr( &mut self, ptr: HotFnPtr, args: A, ) -> Result<F::Return, Infallible>

Call the function at ptr directly, bypassing the jump table.

ptr is consulted on every call, in every build profile (release included): the table is never read and no fall-through is recorded.

§Safety

For a HotFn::current value, ptr must be this monomorphisation’s call_it (signature fn(&mut F, A) -> F::Return) or its patched equivalent. For a HotFn::from_fn_ptr value, ptr must be a function of type F: the pointer’s own target or its patched equivalent. Either way the argument and return layouts (for HotFn::current, F’s own layout too: a closure’s captures) must not have changed since ptr was taken. HotFn::ptr_address on a HotFn built the same way returns such an address.

Auto Trait Implementations§

§

impl<A, M, F> Freeze for HotFn<A, M, F>
where F: Freeze, Option<FnPointerOps<A, <F as HotFunction<A, M>>::Return, F>>: Freeze, PhantomData<(A, M)>: Freeze,

§

impl<A, M, F> RefUnwindSafe for HotFn<A, M, F>
where F: RefUnwindSafe, Option<FnPointerOps<A, <F as HotFunction<A, M>>::Return, F>>: RefUnwindSafe, PhantomData<(A, M)>: RefUnwindSafe,

§

impl<A, M, F> Send for HotFn<A, M, F>
where F: Send, Option<FnPointerOps<A, <F as HotFunction<A, M>>::Return, F>>: Send, PhantomData<(A, M)>: Send,

§

impl<A, M, F> Sync for HotFn<A, M, F>
where F: Sync, Option<FnPointerOps<A, <F as HotFunction<A, M>>::Return, F>>: Sync, PhantomData<(A, M)>: Sync,

§

impl<A, M, F> Unpin for HotFn<A, M, F>
where F: Unpin, Option<FnPointerOps<A, <F as HotFunction<A, M>>::Return, F>>: Unpin, PhantomData<(A, M)>: Unpin,

§

impl<A, M, F> UnsafeUnpin for HotFn<A, M, F>
where F: UnsafeUnpin, Option<FnPointerOps<A, <F as HotFunction<A, M>>::Return, F>>: UnsafeUnpin, PhantomData<(A, M)>: UnsafeUnpin,

§

impl<A, M, F> UnwindSafe for HotFn<A, M, F>
where F: UnwindSafe, Option<FnPointerOps<A, <F as HotFunction<A, M>>::Return, F>>: UnwindSafe, PhantomData<(A, M)>: UnwindSafe,

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 = !

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

fn try_from(value: U) -> Result<T, !>

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.