use std::string::ToString;
use std::collections::HashMap;
use tokio_core::reactor::{Core, Handle};
use futures::sync::oneshot::{channel, Receiver, Sender};
use actor::{Actor, Handler, ResponseType};
use address::SyncAddress;
use arbiter::Arbiter;
use context::Context;
use msgs::{SystemExit, StopArbiter};
use message::Response;
pub struct System {
stop: Option<Sender<i32>>,
arbiters: HashMap<String, SyncAddress<Arbiter>>,
}
impl Actor for System {
type Context = Context<Self>;
}
impl System {
#[cfg_attr(feature="cargo-clippy", allow(new_ret_no_self))]
pub fn new<T: ToString>(name: T) -> SystemRunner {
let core = Arbiter::new_system(name.to_string());
let (stop_tx, stop_rx) = channel();
let sys = System {
arbiters: HashMap::new(), stop: Some(stop_tx)}.start();
Arbiter::set_system(sys, name.to_string());
SystemRunner {
core: core,
stop: stop_rx,
}
}
}
#[must_use="SystemRunner must be run"]
pub struct SystemRunner {
core: Core,
stop: Receiver<i32>,
}
impl SystemRunner {
pub fn handle(&self) -> &Handle {
Arbiter::handle()
}
pub fn run(self) -> i32 {
let SystemRunner { mut core, stop, ..} = self;
match core.run(stop) {
Ok(code) => code,
Err(_) => 1,
}
}
}
impl Handler<SystemExit> for System {
fn handle(&mut self, msg: SystemExit, _: &mut Context<Self>) -> Response<Self, SystemExit>
{
for addr in self.arbiters.values() {
addr.send(StopArbiter(msg.0));
}
if let Some(stop) = self.stop.take() {
let _ = stop.send(msg.0);
}
Self::empty()
}
}
pub(crate) struct RegisterArbiter(pub String, pub SyncAddress<Arbiter>);
#[doc(hidden)]
impl ResponseType for RegisterArbiter {
type Item = ();
type Error = ();
}
#[doc(hidden)]
impl Handler<RegisterArbiter> for System {
fn handle(&mut self, msg: RegisterArbiter, _: &mut Context<Self>)
-> Response<Self, RegisterArbiter>
{
self.arbiters.insert(msg.0, msg.1);
Self::empty()
}
}
pub(crate) struct UnregisterArbiter(pub String);
#[doc(hidden)]
impl ResponseType for UnregisterArbiter {
type Item = ();
type Error = ();
}
#[doc(hidden)]
impl Handler<UnregisterArbiter> for System {
fn handle(&mut self, msg: UnregisterArbiter, _: &mut Context<Self>)
-> Response<Self, UnregisterArbiter>
{
self.arbiters.remove(&msg.0);
Self::empty()
}
}