Skip to main content

NativeContext

Struct NativeContext 

Source
pub struct NativeContext<'a> { /* private fields */ }
Expand description

The capability surface a handler is given for exactly one slice.

Borrows the running Process and the shared services. All sends route through LocalSendFacility (so sender-clock ticking and replay validation are reused verbatim); spawns route through SpawnFacility.

Implementations§

Source§

impl<'a> NativeContext<'a>

Source

pub fn readiness_facility(&self) -> Option<&dyn ReadinessFacility>

Return the in-slice readiness facility when the scheduler composed it.

None is the Disabled service’s typed absence: handlers can refuse the operation while still runnable instead of parking without an armed fd.

Source

pub fn self_pid(&self) -> u64

PID of the running native process.

Source

pub fn has_messages(&self) -> bool

True when there is at least one queued message to drain this slice.

Source

pub fn trap_exit(&self) -> bool

True when this native process is trapping exits.

Source

pub fn set_trap_exit(&mut self, value: bool) -> bool

Enable or disable exit trapping for this native process — the native equivalent of process_flag(trap_exit, true). Returns the previous value.

When trapping is enabled, an exit signal from a linked process is converted into an {'EXIT', source, reason} message and delivered to this process’s mailbox (drained at the slice boundary by the SAME shared store-back the bytecode path uses) instead of terminating it — so a native handler can supervise linked children. This flips the flag on the underlying Process, the single source of truth the pid-keyed propagate_exit path consults; it adds no native-specific trap state.

Source

pub fn recv(&mut self) -> Option<Term>

Remove and return the next mailbox message in arrival order, or None when the mailbox is empty.

Implemented over the existing Mailbox API (current_message then remove_current_message) — it adds no new mailbox method. The returned term references this process’s own heap and is valid for the rest of the slice.

Source

pub fn skip_message(&mut self)

Advance the selective-receive save pointer past the current message without removing it (the Mailbox skip primitive), for handlers that want to leave a message in place and scan the next one.

Source

pub fn send(&mut self, target_pid: u64, message: Term)

Send message to target_pid, routed through the existing LocalSendFacility.

Ticks this process’s logical clock before delivery and passes the sender_clock through, exactly like interpreter::opcodes::messaging. On a replay mismatch the clock tick is rolled back and the error is recorded for run_native_slice to surface as an exit, so replay stays deterministic. A self-send lands in the process’s own Executing slot and is merged into the mailbox at store-back (no special case here).

Source

pub fn alloc_tuple(&mut self, elements: &[Term]) -> Option<Term>

Allocate a tuple of elements on this process’s heap and return the tuple term, or None when the heap is full.

This is the allocation primitive an crate::native::actor::ActorMessage encode implementation uses to build a compound message of immediates/scalars. Every element MUST be an immediate (small integer, atom, local pid) or a heap term already rooted on this process’s heap: the native slice performs no garbage collection, so this allocator neither triggers a GC nor needs to root its arguments. Raw closures with free variables must NOT be exchanged this way (the pre-existing ETF closure-encoding limitation documented on this module); actors exchange immediates/refs/scalars only.

Source

pub fn alloc_owned_term(&mut self, owned: &OwnedTerm) -> Option<Term>

Deep-copy a self-contained crate::ets::OwnedTerm graph onto this process’s heap and return the rooted term, or None when the heap is full or the copy fails.

This is the delivery primitive a dynamic crate::native::actor::Actor uses when its Call/Reply/Cast payload is carried as an opaque, already-detached term graph (e.g. a host value marshalled outside a slice) rather than rebuilt element by element with Self::alloc_tuple. It reuses the same copy_term_to_heap deep-copier ETS delivery uses, so the resulting term is rooted on this heap and valid for the rest of the slice; the native slice performs no GC, so no rooting of the argument is required.

Source

pub fn spawn_native( &mut self, factory: NativeHandlerFactory, link_to: Option<u64>, ) -> Result<u64, SpawnError>

Spawn a native child from factory, optionally linking it to this process, delegating to the same SpawnFacility the scheduler uses.

Source

pub fn schedule(&mut self, delay: Duration, message: Term) -> Option<TimerRef>

Schedule message to be delivered to this process’s mailbox after delay (a self-tick). Returns the timer reference, or None when the context was built without a timer wheel.

The timer is a Deliver timer: when it fires the scheduler pushes message into this process’s mailbox (via the same Executing-slot-safe path that send/IO delivery use) and wakes it, so a handler that returns NativeOutcome::Wait is rescheduled when the tick lands.

Source

pub fn send_after( &mut self, delay: Duration, target_pid: u64, message: Term, ) -> Option<TimerRef>

Schedule message to be delivered to target_pid’s mailbox after delay. Returns the timer reference, or None when the context was built without a timer wheel.

§Replay determinism

Unlike Self::send, scheduling a timer is NOT itself a replay-recorded or replay-validated event — and deliberately so, to stay identical to the erlang:send_after/start_timer BIF path (ProcessContext::schedule_timer), which also does not record the scheduling call. The replayed event is the timer expiry: under replay tick_replay_timers discards the live wheel’s wall-clock fires and instead replays the recorded TimerExpiry set through expire_timers, so the delivered message and its ordering come from the log, not from wall-clock timing. The scheduled entry left in the live wheel is inert under replay (its real fire is discarded). Native timers are therefore exactly as replay-deterministic as BIF timers; what they do NOT add is the per-call determinism validation that send performs, because timer scheduling has no recorded counterpart to validate against.

Source

pub fn cancel_timer(&mut self, reference: TimerRef) -> Option<Duration>

Cancel a pending timer scheduled through this context, returning its remaining duration. None when there is no timer wheel or the timer already fired or was already cancelled.

Source

pub fn start_async(&mut self, mfa: NativeKey, args: &[Term]) -> Result<(), Term>

Start host async work through the SAME async-NIF seam the bytecode path uses, then park this process pending completion (WR-7).

mfa names a host async native (the key the host registered with its WasmAsyncNifFacility); args are immediate/heap terms rooted on this process’s heap. The facility starts the host operation (e.g. a browser fetch/OPFS Promise) bound to this process’s pid and arranges a later crate::scheduler::WasmScheduler::complete_async callback. The handler MUST return NativeOutcome::Wait after a successful start_async: the completion is delivered into this process’s mailbox on a later turn (the scheduler converts the pid-keyed completion into a {ok, Value} / {error, Reason} message), and the handler reads it with NativeContext::recv when it next runs — exactly the wake-on-message resume model call_async uses.

Returns Ok(()) when the host op was started (now park), or Err(reason) when no facility is installed or the host rejected synchronously (in which case the process is NOT parked and the handler should handle reason).

§Errors

Returns the host’s error term, or an undef atom when no WasmAsyncNifFacility is installed.

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for NativeContext<'a>

§

impl<'a> !Send for NativeContext<'a>

§

impl<'a> !Sync for NativeContext<'a>

§

impl<'a> !UnwindSafe for NativeContext<'a>

§

impl<'a> Freeze for NativeContext<'a>

§

impl<'a> Unpin for NativeContext<'a>

§

impl<'a> UnsafeUnpin for NativeContext<'a>

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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
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.