pub struct ImmediateValuePromise<T: Send> { /* private fields */ }
Expand description

A promise which can be easily created and stored.

Introduction

Will spawn a task to resolve the future immediately. No possibility to read out intermediate values or communicate progress. One can use Option<ImmediateValuePromise<T>> inside state structs to make this class somewhat lazy. That may be an option if you don’t need any progress indication or intermediate values. After the calculation is done, ImmediateValuePromise<T> can be read out without mutability requirement using ImmediateValuePromise::get_state which also yields an ImmediateValueState but without requiring mut. Another useful feature after calculation is finished, is that you can use ImmediateValuePromise::poll_state_mut to get a mutable ImmediateValueState which allows you to take ownership of inner values with ImmediateValueState::take_value or get a mutable reference to the inner via ImmediateValueState::get_value_mut.

Examples

Basic usage

use std::fs::File;
use std::thread;
use std::time::Duration;
use lazy_async_promise::{ImmediateValuePromise, ImmediateValueState};
let mut oneshot_val = ImmediateValuePromise::new(async {
    tokio::time::sleep(Duration::from_millis(50)).await;
    let test_error_handling = false;
    if test_error_handling {
      // We can use the ?-operator for most errors in our futures
      let _file = File::open("I_DONT_EXIST_ERROR")?;
    }
    // return the value wrapped in Ok for the result here
    Ok(34)
});
assert!(matches!(
    oneshot_val.poll_state(),
    ImmediateValueState::Updating
));
thread::sleep(Duration::from_millis(100));
let result = oneshot_val.poll_state();
if let ImmediateValueState::Success(val) = result {
    assert_eq!(*val, 34);
} else {
    unreachable!();
}

Modifying inner values or taking ownership

use std::thread;
use std::time::Duration;
use lazy_async_promise::{DirectCacheAccess, ImmediateValuePromise, ImmediateValueState};
let mut oneshot_val = ImmediateValuePromise::new(async {
    Ok(34)
});
thread::sleep(Duration::from_millis(50));
assert!(matches!(
    oneshot_val.poll_state(),
    ImmediateValueState::Success(_)
));
let result = oneshot_val.poll_state_mut();
// we got the value, take a mutable ref
if let ImmediateValueState::Success(inner) = result {
  *inner=32;
}
else {
  unreachable!();
}
assert!(result.get_value_mut().is_some());
// take it out
let value = result.take_value();
assert_eq!(value.unwrap(), 32);

Optional laziness

Option<ImmediateValuePromise> is a nice way to implement laziness with get_or_insert or get_or_insert_with. Unfortunately, using these constructs becomes cumbersome. To ease the pain, we blanket-implement DirectCacheAccess for any Option<DirectCacheAccess<T>>.

use std::thread;
use std::time::Duration;
use lazy_async_promise::{DirectCacheAccess, ImmediateValuePromise};
#[derive(Default)]
struct State {
  promise: Option<ImmediateValuePromise<i32>>
}

let mut state = State::default();
let promise_ref = state.promise.get_or_insert_with(|| ImmediateValuePromise::new(async {
    Ok(34)
}));
promise_ref.poll_state();
thread::sleep(Duration::from_millis(50));
//now let's assume we forgot about our lease already and want to get the value again:
let value_opt = state.promise.as_ref().unwrap().get_value(); // <- dangerous
let value_opt = state.promise.as_ref().and_then(|i| i.get_value()); // <- better, but still ugly
let value_opt = state.promise.get_value(); // <- way nicer!
assert!(value_opt.is_some());
assert_eq!(*value_opt.unwrap(), 34);

Implementations§

source§

impl<T: Send + 'static> ImmediateValuePromise<T>

source

pub fn new<U: Future<Output = Result<T, BoxedSendError>> + Send + 'static>( updater: U ) -> Self

Creator, supply a future which returns Result<T, Box<dyn Error + Send>. Will be immediately spawned via tokio.

source

pub fn poll_state(&mut self) -> &ImmediateValueState<T>

Poll the state updating the internal state from the running thread if possible, will return the data or error if ready or updating otherwise.

source

pub fn poll_state_mut(&mut self) -> &mut ImmediateValueState<T>

Poll the state, return a mutable ref to to the state

source

pub fn get_state(&self) -> &ImmediateValueState<T>

Get the current state without pulling. No mutability required

Trait Implementations§

source§

impl<T: Send + 'static> DirectCacheAccess<T> for ImmediateValuePromise<T>

source§

fn get_value_mut(&mut self) -> Option<&mut T>

returns mutable reference to the cache if applicable
source§

fn get_value(&self) -> Option<&T>

returns a reference to the cache if applicable
source§

fn take_value(&mut self) -> Option<T>

takes the value and leaves the promise in a valid state indicating its emptiness

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere 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 Twhere 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 Twhere U: Into<T>,

§

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 Twhere U: TryFrom<T>,

§

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.