use futures::{future, prelude::*};
use holly::{Error, prelude::*};
use tokio_threadpool::ThreadPool;
struct Root;
enum RootMsg {
Start,
FromChild(Hello)
}
impl From<Hello> for RootMsg {
fn from(h: Hello) -> Self {
RootMsg::FromChild(h)
}
}
struct Child {
parent: Addr<RootMsg, Hello>
}
struct ChildMsg;
#[derive(Debug)]
struct Hello;
impl Actor<RootMsg, Error> for Root {
type Result = Box<dyn Future<Item = State<Self, RootMsg>, Error = Error> + Send>;
fn process(self, ctx: &mut Context<RootMsg>, msg: Option<RootMsg>) -> Self::Result {
match msg {
Some(RootMsg::Start) => {
let child = Child { parent: ctx.address().cast() };
let future = future::result(ctx.scheduler().spawn(child))
.and_then(|addr| addr.send(ChildMsg))
.map(move |_| State::Ready(self));
Box::new(future)
}
Some(RootMsg::FromChild(m)) => {
println!("Received message from child: {:?}", m);
Box::new(future::ok(State::Done))
}
None => {
Box::new(future::ok(State::Done))
}
}
}
}
impl Actor<ChildMsg, Error> for Child {
type Result = Box<dyn Future<Item = State<Self, ChildMsg>, Error = Error> + Send>;
fn process(self, _ctx: &mut Context<ChildMsg>, _msg: Option<ChildMsg>) -> Self::Result {
Box::new(self.parent.send(Hello).map(|_| State::Done))
}
}
#[test]
fn parent_child() -> Result<(), Error> {
let pool = ThreadPool::new();
let exec = Scheduler::new(pool.sender().clone());
let mut root = exec.spawn(Root)?;
root.send_now(RootMsg::Start)?;
pool.shutdown_on_idle().wait().unwrap();
Ok(())
}