Struct ThreadBoundRunner

Source
pub struct ThreadBoundRunner<ThreadState> {
    call_channel_tx: Sender<CallRequest<ThreadState>>,
}
Expand description

A runner that takes a non-Send state and makes it Send compatible.

ThreadBoundRunner is designed to safely encapsulate a !Send state object by pinning it to a single thread using spawn_local. It provides a Send API that allows other threads to submit tasks (function pointers or closures) that operate on the thread-bound state.

Tasks are queued via an internal channel and are executed sequentially on the owning thread.

§Example

use bitwarden_threading::ThreadBoundRunner;

struct State;

impl State {
    pub async fn do_something(&self, some_input: i32) -> i32 {
        return some_input;
    }
}

let runner = ThreadBoundRunner::new(State);
let input = 42;

let output = runner.run_in_thread(move |state| async move {
  return state.do_something(input).await;
}).await;

assert_eq!(output.unwrap(), 42);

If you need mutable access to the state, you can wrap the ThreadState in a Mutex or RwLock and use the run_in_thread method to lock it before accessing it.

§Example

use bitwarden_threading::ThreadBoundRunner;
use tokio::sync::Mutex;

struct State(i32);

let runner = ThreadBoundRunner::new(Mutex::new(State(0)));

runner.run_in_thread(|state| async move {
  state.lock().await.0 += 1;
}).await;

This pattern is useful for interacting with APIs or data structures that must remain on the same thread, such as GUI toolkits, WebAssembly contexts, or other thread-bound environments.

Fields§

§call_channel_tx: Sender<CallRequest<ThreadState>>

Implementations§

Source§

impl<ThreadState> ThreadBoundRunner<ThreadState>
where ThreadState: 'static,

Source

pub fn new(state: ThreadState) -> Self

Source

pub async fn run_in_thread<F, Fut, Output>( &self, function: F, ) -> Result<Output, CallError>
where F: FnOnce(Rc<ThreadState>) -> Fut + Send + 'static, Fut: Future<Output = Output>, Output: Send + Sync + 'static,

Submit a task to be executed on the thread-bound state.

The provided function is executed on the thread that owns the internal ThreadState, ensuring safe access to !Send data. Tasks are dispatched in the order they are received, but because they are asynchronous, multiple tasks may be in-flight and running concurrently if their futures yield.

§Returns

A future that resolves to the result of the function once it has been executed.

Trait Implementations§

Source§

impl<ThreadState: Clone> Clone for ThreadBoundRunner<ThreadState>

Source§

fn clone(&self) -> ThreadBoundRunner<ThreadState>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<ThreadState> Freeze for ThreadBoundRunner<ThreadState>

§

impl<ThreadState> RefUnwindSafe for ThreadBoundRunner<ThreadState>

§

impl<ThreadState> Send for ThreadBoundRunner<ThreadState>

§

impl<ThreadState> Sync for ThreadBoundRunner<ThreadState>

§

impl<ThreadState> Unpin for ThreadBoundRunner<ThreadState>

§

impl<ThreadState> UnwindSafe for ThreadBoundRunner<ThreadState>

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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.