use std::sync::Mutex;
use super::attempt_cancel_token::AttemptCancelToken;
use super::blocking_attempt::BlockingAttempt;
use crate::AttemptFailure;
pub(in crate::executor) struct BlockingValueOperation<T, F> {
operation: F,
value: Mutex<Option<T>>,
}
impl<T, F> BlockingValueOperation<T, F> {
pub(in crate::executor) fn new(operation: F) -> Self {
Self {
operation,
value: Mutex::new(None),
}
}
pub(in crate::executor) fn take_value(&self) -> T {
let mut value = self
.value
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
value
.take()
.expect("retry loop succeeded without an operation value")
}
}
impl<T, E, F> BlockingAttempt<E> for BlockingValueOperation<T, F>
where
T: Send + 'static,
E: Send + 'static,
F: Fn(AttemptCancelToken) -> Result<T, E> + Send + Sync + 'static,
{
fn call(&self, token: AttemptCancelToken) -> Result<(), AttemptFailure<E>> {
match (self.operation)(token) {
Ok(result) => {
let mut value = self
.value
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
*value = Some(result);
Ok(())
}
Err(error) => Err(AttemptFailure::Error(error)),
}
}
}