Skip to main content

EngineHost

Struct EngineHost 

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

A shared, thread-safe front end to one engine.

The engine is a single-threaded-apartment COM object: its wrappers are deliberately neither Send nor Sync, and driving one from several threads does not work. A server, though, is inherently multi-threaded.

This resolves that by giving the engine a thread of its own. Callers submit work; the engine thread runs it and sends the answer back. Because the work is a closure rather than a fixed command list, the whole API is reachable without enumerating it:

use rs_teststand_bridge::EngineHost;

let host = EngineHost::start()?;
let version = host.with_engine(|engine| engine.version_string()).await??;
println!("TestStand {version}");

The same thread polls the message queue and broadcasts what it finds, so a host can serve requests and forward progress at once, which is what an IPC layer needs and what a single-threaded caller cannot do.

Implementations§

Source§

impl EngineHost

Source

pub fn start() -> Result<Self, Error>

Starts an engine on a dedicated thread.

Message polling is enabled, so anything a sequence posts reaches subscribe without further setup.

§Errors

Error if the engine cannot be created.

Source

pub async fn with_engine<F, T>(&self, work: F) -> Result<T, Error>
where F: FnOnce(&Engine) -> T + Send + 'static, T: Send + 'static,

Runs a closure against the engine and waits for its result.

The closure runs on the engine’s thread, so it may use any part of the API. Its result must be Send to come back.

The outer error means the engine thread is gone; the inner one is whatever the closure produced.

§Errors

Error if the engine thread has stopped.

Source

pub fn subscribe(&self) -> Receiver<MessageEvent>

Receives every message posted from now on.

Each subscriber gets its own copy. One that falls further behind than the backlog is told how many it missed rather than quietly losing them.

Source

pub fn subscriber_count(&self) -> usize

How many subscribers are currently listening.

Trait Implementations§

Source§

impl Debug for EngineHost

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Drop for EngineHost

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

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

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. 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.