Last active
June 26, 2016 21:21
-
-
Save fero23/54ce05daa707b1071ccb13b3bbac45ac to your computer and use it in GitHub Desktop.
Proof of concept design for an async library
This file contains hidden or 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
use std::marker::PhantomData; | |
use std::sync::{Arc, Mutex}; | |
use std::thread; | |
//use std::alloc::arc::Weak; | |
#[derive(Debug)] | |
enum Promise<O> { | |
Awaiting, | |
ResultValue(Arc<Mutex<O>>) | |
} | |
trait Event<O> { | |
fn fire(&mut self) -> Option<Arc<Mutex<O>>>; | |
fn try_get(&self) -> Option<Arc<Mutex<O>>>; | |
} | |
struct GeneratorEvent<I, D, DO, O, F> { | |
input_data: I, | |
dependencies: D, | |
deps_ret_types: PhantomData<DO>, | |
handler: F, | |
promise: Promise<O> | |
} | |
trait DepsTuple<R> { | |
fn try_get_all(&self) -> Option<R>; | |
} | |
impl DepsTuple<()> for () { | |
fn try_get_all(&self) -> Option<()> { | |
Some(()) | |
} | |
} | |
impl<A, B, AO, BO> DepsTuple<(Arc<Mutex<AO>>, Arc<Mutex<BO>>)> | |
for (Arc<Mutex<A>>, Arc<Mutex<B>>) | |
where A: Event<AO>, | |
B: Event<BO> | |
{ | |
fn try_get_all(&self) -> Option<(Arc<Mutex<AO>>, Arc<Mutex<BO>>)> { | |
if let (Some(a0), Some(b0)) = | |
(self.0.lock().ok().and_then(|a0| a0.try_get()), | |
self.1.lock().ok().and_then(|a1| a1.try_get())) { | |
Some((a0, b0)) | |
} else { | |
None | |
} | |
} | |
} | |
impl<I, D, DO, O, F> Event<O> for GeneratorEvent<I, D, DO, O, F> | |
where D: DepsTuple<DO>, | |
F: FnMut(&I, DO) -> O | |
{ | |
fn fire(&mut self) -> Option<Arc<Mutex<O>>> { | |
match self.promise { | |
Promise::Awaiting => { | |
if let Some(deps) = self.dependencies.try_get_all() { | |
let val = (self.handler)(&self.input_data, deps); | |
self.promise = | |
Promise::ResultValue(Arc::new(Mutex::new(val))); | |
if let Promise::ResultValue(ref val) = self.promise { | |
Some(val.clone()) | |
} else { | |
None | |
} | |
} else { | |
None | |
} | |
} | |
Promise::ResultValue(ref mut val) => Some(val.clone()) | |
} | |
} | |
fn try_get(&self) -> Option<Arc<Mutex<O>>> { | |
match self.promise { | |
Promise::ResultValue(ref val) => Some(val.clone()), | |
_ => None | |
} | |
} | |
} | |
fn main() { | |
let d1 = Arc::new(Mutex::new(GeneratorEvent { | |
input_data: "Tom".to_string(), | |
dependencies: (), | |
handler: |input: &String, _| input.to_uppercase(), | |
deps_ret_types: PhantomData, | |
promise: Promise::Awaiting | |
})); | |
let d2 = Arc::new(Mutex::new(GeneratorEvent { | |
input_data: "Jeanne".to_string(), | |
dependencies: (), | |
handler: |input: &String, _| input.to_uppercase(), | |
deps_ret_types: PhantomData, | |
promise: Promise::Awaiting | |
})); | |
let mut g1 = GeneratorEvent { | |
input_data: 2, | |
dependencies: (d1.clone(), d2.clone()), | |
handler: |input: &_, | |
(d1, d2): (Arc<Mutex<String>>, Arc<Mutex<String>>)| | |
format!("{} AND {} ARE MARRIED AND THEY HAVE {} KIDS", | |
d1.lock().unwrap().to_string(), | |
d2.lock().unwrap().to_string(), | |
input), | |
deps_ret_types: PhantomData, | |
promise: Promise::Awaiting | |
}; | |
let handles = vec![thread::spawn(move || { | |
println!("firing from thread 1"); | |
d1.lock().unwrap().fire(); | |
}), thread::spawn(move || { | |
println!("firing from thread 2"); | |
d2.lock().unwrap().fire(); | |
})]; | |
for h in handles.into_iter() { | |
h.join().unwrap(); | |
} | |
println!("{:?}", g1.fire()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment