Agent

Struct Agent 

Source
pub struct Agent<C: ?Sized + Config, I: ?Sized + Any, A: Actions<C, I>, S = Unchecked> { /* private fields */ }
Expand description

Represents an isolated execution context (an agent) within the simulation.

An Agent encapsulates:

  • Subject: The data associated with this agent.
  • Lifecycle: The asynchronous logic defining its behavior.
  • Execution State: Manages whether the agent is ready, running, or finished.

Agents provide isolation: their internal logic, defined via the Actions (and typically Behavior) trait, cannot directly access or be influenced by the lexical scope where the Agent struct was created, due to the HRTB mechanism employed by Actions. Communication happens through simulation primitives (scheduling, waiting) and the agent’s final Output.

Agent implements Deref and DerefMut to its subject. However, mutable access is only practically possible before the agent is passed to Sim::activate, as activation blocks the access path. This is enforced by Rust’s borrowing rules at compile time.

Agents are typically created using Agent::new (for types implementing Behavior) or Agent::build for more configuration options. They must be pinned (e.g., using core::pin::pin!) before being passed to Sim::activate.

The generic parameter S defines the Settle strategy, controlling how the agent’s Output is translated into an ExitStatus. Unchecked is the default, treating all outcomes as success. Checked interprets Result, Option, and bool as success/failure indicators.

§Type Parameters

  • C: The simulation configuration type (Config).
  • I: The type of the agent’s internal state (the “item” or “subject”).
  • A: The type implementing Actions, defining the agent’s lifecycle logic.
  • S: The Settle strategy (defaults to Unchecked).

§Safety Warning

The order of fields inner and item must not be changed. inner must come before item. Reversing this order will lead to use-after-free and undefined behavior because the Share within Inner::Live internally holds a pointer derived from item, and drop order relies on inner being dropped first.

Implementations§

Source§

impl Agent<(), (), Pending<()>>

Source

pub fn new<'p, C, I>( subject: I, ) -> Lease<'p, Agent<C, I, impl Actions<C, I, Output = I::Output> + use<C, I>>>
where C: ?Sized + Config, I: Any + Behavior<C>,

Creates a new Agent using a type that implements Behavior.

This is the simplest way to create an agent. It infers the agent’s actions, output type, and name from the Behavior implementation of I. The agent uses the default Unchecked settle strategy, meaning its ExitStatus will always be Ok unless it panics or is aborted, regardless of the Output type (even if it’s a Result::Err).

The provided subject (of type I) becomes the agent’s internal state.

Returns a Lease, which must be pinned before activation.

§Example
struct MyAgent;
impl Behavior for MyAgent {
    type Output = ();
    async fn actions(&self, sim: &Sim) { /* ... */ }
}
let agent_lease = Agent::new(MyAgent);
let pinned_agent = pin!(agent_lease);
// Pass pinned_agent to sim.activate(...)
Source

pub const fn build<C: ?Sized + Config>() -> Builder<C>

Creates a Builder for configuring an Agent instance.

Use the builder when you need to customize options like the agent’s name, initial rank, settle strategy (Checked), or source code location, or when defining the agent using a state/function tuple instead of a dedicated Behavior implementation.

§Example
let agent = Agent::build()
    .with_subject(MyState)
    .with_actions(my_actions)
    .with_name("CustomAgent")
    .finish();
// Pin and activate agent...

Trait Implementations§

Source§

impl<C, I, A, S> Active<C> for Agent<C, I, A, S>
where C: ?Sized + Config, I: Any, A: Actions<C, I>, S: Settle<A::Output>,

Source§

fn bind<'p>( this: Pin<LeasedMut<'p, Self>>, sctx: &'p Share<C>, ) -> Self::Puck<'p>

Binds the agent to the simulation context, transitioning it from Born to Live.

This method is called internally by Sim::activate. It performs the critical steps:

  1. Temporarily replaces the Inner::Born state with Inner::Bust.
  2. Calls the action.bind() method (from private::Action) to create the agent’s lifecycle future (RootFuture).
  3. If bind succeeds, creates the Share context and the RootJob.
  4. Replaces the Inner::Bust state with Inner::Live, containing the RootJob and Share.
  5. Returns the agent’s Puck handle.

If action.bind() panics, the agent remains in the Inner::Bust state.

§Safety

Relies on unsafe blocks for lifetime transmutation ('p to 'static and back) and creating the Share context. These are justified because:

  • The 'static lifetime on RootJob within Inner::Live is an internal implementation detail; the actual future only borrows data for 'p. The lifetime is transmuted back to 'p when creating the Puck.
  • Share::new requires ensuring the item pointer outlives Share. This is guaranteed by the struct field ordering (inner before item), and Rust’s drop order guarantees (inner is dropped first).
Source§

type Output = <A as Actions<C, I>>::Output

Associated result type once the active object terminates.
Source§

type Puck<'p> = Puck<'p, C, I, A, S> where Self: 'p

The type of join handle returned from the bind-method that implements the Puck trait.
Source§

impl<C, I, A, S> Deref for Agent<C, I, A, S>
where C: ?Sized + Config, I: ?Sized + Any, A: Actions<C, I>,

Source§

type Target = I

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<C, I, A, S> DerefMut for Agent<C, I, A, S>
where C: ?Sized + Config, I: ?Sized + Any, A: Actions<C, I>,

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
Source§

impl<C, I, A, S> Dispatch for Agent<C, I, A, S>
where C: ?Sized + Config, I: ?Sized + Any, A: Actions<C, I>, S: Settle<A::Output>,

Source§

fn poll(self: Pin<&Self>, cx: &mut Context<'_>) -> Poll<ExitStatus>

Called to advance the Active object.
Source§

fn reclaim(self: Pin<&mut Self>)

Called when the reference counter of an instance is reduced to 0. Read more

Auto Trait Implementations§

§

impl<C, I, A, S = Unchecked> !Freeze for Agent<C, I, A, S>

§

impl<C, I, A, S = Unchecked> !RefUnwindSafe for Agent<C, I, A, S>

§

impl<C, I, A, S = Unchecked> !Send for Agent<C, I, A, S>

§

impl<C, I, A, S = Unchecked> !Sync for Agent<C, I, A, S>

§

impl<C, I, A, S = Unchecked> !UnwindSafe for Agent<C, I, A, S>

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

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Stateful for T
where T: Deref, <T as Deref>::Target: Stateful,

Source§

type Brand = <<T as Deref>::Target as Stateful>::Brand

Associated marker type for the branding.
Source§

unsafe fn enter(&self)

Method hook used to register the creation of another Ephemeral-token for this instance. Read more
Source§

unsafe fn leave(&self)

Method hook used to register the destruction of a Ephemeral-token for this instance. 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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more