Skip to content

Instantly share code, notes, and snippets.

@fero23
Last active June 26, 2016 21:21
Show Gist options
  • Save fero23/54ce05daa707b1071ccb13b3bbac45ac to your computer and use it in GitHub Desktop.
Save fero23/54ce05daa707b1071ccb13b3bbac45ac to your computer and use it in GitHub Desktop.
Proof of concept design for an async library
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