Created
March 29, 2022 15:42
-
-
Save hsfzxjy/a73fec285cf51006c39daf262b7f2e76 to your computer and use it in GitHub Desktop.
Rust Deferred
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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