Skip to content

Instantly share code, notes, and snippets.

@hsfzxjy
Created March 29, 2022 15:42
Show Gist options
  • Save hsfzxjy/a73fec285cf51006c39daf262b7f2e76 to your computer and use it in GitHub Desktop.
Save hsfzxjy/a73fec285cf51006c39daf262b7f2e76 to your computer and use it in GitHub Desktop.
Rust Deferred
pub mod sync {
use crate::prelude::*;
use std::ops::{Deref, DerefMut};
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum DeferredState {
Created,
Pending,
Resolved,
Rejected,
}
use DeferredState::*;
struct DeferredInner<T> {
inner: T,
state: DeferredState,
}
pub struct DeferredGuard<'a, T>(std::sync::MutexGuard<'a, DeferredInner<T>>);
impl<'a, T> Deref for DeferredGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0.deref().inner
}
}
impl<'a, T> DerefMut for DeferredGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0.deref_mut().inner
}
}
impl<'a, T> DeferredGuard<'a, T> {
pub fn complete<U, E>(
mut self,
res: std::result::Result<U, E>,
) -> std::result::Result<U, E> {
match res {
Ok(_) => self.resolve(),
Err(_) => self.reject(),
};
res
}
pub fn resolve(&mut self) {
self.0.deref_mut().state = Resolved;
}
pub fn reject(&mut self) {
self.0.deref_mut().state = Rejected;
}
}
#[derive(Clone)]
pub struct Deferred<T>(Arc<Mutex<DeferredInner<T>>>);
impl<T> Deferred<T> {
pub fn new(v: T) -> Self {
Self(
Mutex::new(DeferredInner {
inner: v,
state: Created,
})
.into(),
)
}
pub fn clone(&self) -> Self {
Self(self.0.clone())
}
pub fn start(&mut self) -> Result<DeferredGuard<T>> {
let mut guard = self.0.lock().unwrap();
if guard.state != Created {
bail!("Already created");
}
guard.state = Pending;
Ok(DeferredGuard(guard))
}
pub fn wait_complete(self) -> Result<T> {
// let value;
loop {
let state = self.0.lock().map(|x| x.state).unwrap_or(Rejected);
match state {
Created | Pending => {
std::thread::yield_now();
continue;
}
Resolved => {
break;
}
Rejected => bail!("failed"),
}
}
let mut arc = self.0;
loop {
arc = match Arc::try_unwrap(arc) {
Ok(x) => return Ok(x.into_inner().unwrap().inner),
Err(x)=>x
};
// if let Ok(x) = Arc::try_unwrap(self.0) {
// value = x;
// break 'outer;
// }
std::thread::yield_now();
}
// let inner = Arc::try_unwrap(self.0).map_err(|_| anyhow!("Arc is held by others"))?;
// Ok(value.into_inner().unwrap().inner)
}
}
impl<T> From<T> for Deferred<T> {
fn from(v: T) -> Self {
Self::new(v)
}
}
// impl<T> Deref for Deferred<T> {
// type Target = Arc<Mutex<DeferredInner<T>>>;
// fn deref(&self) -> &Self::Target {
// &self.0
// }
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment